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中不一致的情况.
相关推荐
为什么要有GC? GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域...
为什么要有GC? GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域...
为什么要重载? 168 7.5.3 给汽车加个重载的方法 169 7.5.4 测试一下 169 7.5.5 重载容易引发误解的两个地方——返回类型和形参名 170 7.5.6 重载中的最难点——参数匹配原则 171 7.6 使用类的实例作为方法参数...
为什么要重载? 168 7.5.3 给汽车加个重载的方法 169 7.5.4 测试一下 169 7.5.5 重载容易引发误解的两个地方——返回类型和形参名 170 7.5.6 重载中的最难点——参数匹配原则 171 7.6 使用类的实例作为方法参数...
On UNIX Jad skips inner classes if there is more than one class specified in the command line. Jad looks for inner classes in the directory of their top-level container class. 3. List of the command-...
do) -noinner - turn off the support of inner classes (default: on) -nolvt - ignore Local Variable Table information -nonlb - don't output a newline before opening brace (default: do) ...
第10章 内隐类(inner class) 146 10.1 静态类(static class) 146 10.2 成员类(member class) 147 10.3 局部类(local class) 150 10.4 匿名类(anonymous class) 152 10.5 巩固练习 153 第11章 异常处理...
-i - output default initializers for all non-final fields -l<num> - split strings into pieces of maximum <num> chars (default: no) -lnc - annotate the output with line numbers (default: no) -nl - ...
-i - output default initializers for all non-final fields -l<num> - split strings into pieces of maximum <num> chars (default: off) -lnc - annotate the output with line numbers (default: off) -...
class ..................................... 46 Fields and methods ..................... 47 Methods, arguments, and return values ................. 48 The argument list ......................... 49 ...
Fundamentals of the JavaMail API Presented by developerWorks, your source for great tutorials ... Table of Contents If you're viewing this document online, you can click any of the topics below ...