inner class可以分为三种:
1. 定义在class里的普通inner class. 这种inner class可以访问私有变量.
2. 定义在方法里的local inner class. 这种inner class不仅可以访问私有变量, 而且可以访问所在方法的参数, 但这种参数必须为final. 也就是这篇博客要讨论的情况.
3. 定义在方法里的anonymous inner class, 又叫没有名字的local inner class. 这种inner class非常适用于定义callback方法.
为什么local inner class可以访问的变量必须定义为final呢? 我们来看一段代码(代码摘自core java, 卷一)
public void start(int interval, final boolean beep) { class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event) { Date now = new Date(); System.out.println("At the tone, the time is " + now); if (beep) Toolkit.getDefaultToolkit().beep(); } } ActionListener listener = new TimePrinter(); Timer t = new Timer(interval, listener); t.start(); }
可以看到, local inner class TimePrinter访问了beep变量. 由于TimePrinter定义的actionPerformed方法是一个listener方法, 这个方法往往是在程序运行时执行的, 也就是说在它被定义的start(...)方法之后执行的. 而在actionPerformed方法被执行的时候, 其实start(int interval, final boolean beep)中的beep变量已经由于start(int interval, final boolean beep)方法执行完毕, 而从它的堆栈中移除了. 所以, local inner class有必要自己保留一份beep的值. 通过查看编译后的inner class文件:
class TalkingClock$1TimePrinter { TalkingClock$1TimePrinter(TalkingClock, boolean); public void actionPerformed(java.awt.event.ActionEvent); final boolean val$beep; final TalkingClock this$0; }
可以看到, inner class里面所访问的所有对象及变量, 都会被作为参数, 在compiler生成的构造函数中被传入. 这时, beep变量其实相当于在两处被引用了. 一处是start(int interval, final boolean beep), 另一处是inner class的构造函数. 如果beep不是为final的, 那么假如在start(int interval, final boolean beep)方法中可以修改它的值, 就会造成beep的值在start(int interval, final boolean beep)和inner class中不一致的情况.
相关推荐
- 如果要访问方法中的局部变量,则该局部变量必须被声明为final。 2. **final修饰符** - 在Java中,final关键字可以用于修饰变量、方法和类。 - 当用于变量时,表示该变量不可变。 - final局部变量可以在局部...
使用匿名内部类时,如果需要访问外部类方法的参数,那么这些参数必须是`final`的。 ```java public void method(final int num, String str) { // 创建匿名内部类 Runnable runnable = new Runnable() { @...
局部内部类可以访问其所在方法的局部变量,但这些变量必须被声明为`final`。在示例3中,`LocalInnerClassTest`类的`main()`方法内定义了一个局部内部类`InnerClass`,并使用`final`变量`a`,然后在方法内部创建并...
- 在上述例子中,`InnerClass`可以访问`OuterClass`的静态变量`outerVar`。 2. 成员内部类(Non-static Nested Class): - 成员内部类没有`static`修饰符,它们与外部类实例紧密关联,每个外部类实例可以有多个...
由于其局部性,局部内部类可以访问方法内的所有局部变量和参数,但这些变量必须是 final 或 effectively final。局部内部类不能声明为 static,也不能被外部类访问,除非通过方法返回。 4. 匿名内部类(Anonymous ...
局部内部类不能声明为静态,也不能访问方法或块的局部变量,除非这些变量是final的。例如: ```java void someMethod() { final int localVar = 10; class Local { void display() { System.out.println...
- 局部内部类可以访问其所在方法或代码块内的局部变量,但这些变量必须是final或实际上不可变的。 ##### 4. 匿名内部类 匿名内部类是一种没有名字的内部类,常用于简化代码编写,特别是创建接口的实例时。 - **...
3. **方法内部类**(Local Inner Class) 4. **匿名内部类**(Anonymous Inner Class) 这些内部类之间存在一些共性: - **编译后的文件格式**:内部类最终会被编译成独立的`.class`文件,文件名通常为外部类名称...
根据内部类的定义位置不同,我们可以将其分为成员内部类(Member Inner Class)和局部内部类(Local Inner Class)。 #### 成员内部类 成员内部类是定义在外部类成员位置上的内部类。它可以被声明为`public`、`...
方法内部类可以访问方法的局部变量,但这些变量必须是final或effectively final的。方法内部类的实例仅在方法执行期间存在,方法结束后,它们的实例也会被销毁。 ```java class Outer { public void method() { ...
1. **访问权限**:局部内部类可以访问方法内的局部变量,但这些变量必须声明为final。 2. **实例化**:局部内部类只能在其定义的方法或构造函数内部实例化。 3. **示例**: ```java public void method() { final...
它可以访问方法内的所有局部变量,但这些变量必须是最终的(final)。 **代码示例**: ```java public class Outer { public void method() { final int x = 10; class LocalInner { public void printX() { ...
局部内部类必须是最终类,因为它们的引用可以通过方法内的变量传递。 示例代码如下: ```java public class OuterClass { public void method() { final int x = 10; // 局部内部类只能访问最终的局部变量 ...
- 局部内部类可以访问外部方法中的局部变量,但这些变量必须是`final`的。 ```java public class OuterClass { public void outerMethod() { final int y = 20; class LocalInnerClass { public void ...
它可以访问其封闭范围内的final变量和方法,但不能包含任何静态声明。 使用内嵌类的好处包括: - **封装**:内嵌类可以访问外部类的私有成员,提供更好的封装性。 - **代码复用**:内嵌类可以作为工具类,为特定...
它与成员内部类相似,可以访问外部类的成员,但它还能访问该方法中的局部变量,包括final类型的变量。局部内部类不能声明为static,因为它的作用域局限于某个方法或构造器。 ##### 3. 静态内部类(Static Nested ...
匿名内部类可以访问其所在作用域内的所有局部变量,但这些变量必须是final的。 4. 静态内部类(Static Nested Class): 静态内部类与普通的成员内部类类似,但它们可以用 static 关键字声明。这意味着静态内部类...
2. 局部内部类(Local Inner Class):定义在方法、构造器或块中的类,仅在该作用域内可见。 3. 匿名内部类(Anonymous Inner Class):没有名字的内部类,常用于简化单用途的类或接口实现。 4. 静态嵌套类(Static ...
局部类可以访问外部方法中的局部变量,但这些变量必须被声明为`final`。 - **匿名类**:没有显式名称的局部类,通常用于实现接口或继承类。匿名类经常在创建对象时直接定义,例如在事件监听器或简单的接口实现中。 ...