`
自治州
  • 浏览: 34926 次
  • 性别: Icon_minigender_1
  • 来自: 奥克兰
社区版块
存档分类
最新评论

为什么local inner class可以访问的方法参数必须为final

    博客分类:
  • java
 
阅读更多

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中不一致的情况. 

 

 

 

 

 

 

分享到:
评论

相关推荐

    java 面试题 总结

    为什么要有GC?  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域...

    超级有影响力霸气的Java面试题大全文档

    为什么要有GC?  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    为什么要重载? 168 7.5.3 给汽车加个重载的方法 169 7.5.4 测试一下 169 7.5.5 重载容易引发误解的两个地方——返回类型和形参名 170 7.5.6 重载中的最难点——参数匹配原则 171 7.6 使用类的实例作为方法参数...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    为什么要重载? 168 7.5.3 给汽车加个重载的方法 169 7.5.4 测试一下 169 7.5.5 重载容易引发误解的两个地方——返回类型和形参名 170 7.5.6 重载中的最难点——参数匹配原则 171 7.6 使用类的实例作为方法参数...

    Java反编译软件JAD1

    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-...

    java反编译工具jad 1.5.8g(可以反编译jdk1.5,1.6)

    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) ...

    java编程基础,应用与实例

    第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章 异常处理...

    jad.exe+readme.txt

    -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 - ...

    java反编译工具FrontEnd和jad

    -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) -...

    Thinking in Java 4th Edition

    class ..................................... 46 Fields and methods ..................... 47 Methods, arguments, and return values ................. 48 The argument list ......................... 49 ...

    Java邮件开发Fundamentals of the JavaMail API

    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 ...

Global site tag (gtag.js) - Google Analytics