局部内部类为什么只能访问final局部变量?
2015-12-14 21:19
225 查看
//只有定义成 final String obj 才不会报错 public void test(final String obj) { Thread myThread = new Thread() { public void run() { System.out.println(obj); } }; myThread.start(); }
public class OuterClass { public void outerDoSomething() { final String localObj = "hello"; InnerClass innerObj = new class InnerClass { public void innerDoSomething() { // do with localObj } }; } }
如果将一个访问了final的局部变量的内部类进行反编译,可以发现该变量是被作为构造函数的参数传入进去的,当然与之一起传入的参数还有外部类引用this。
实际经过编译,生成的字节码如下:
public class OuterClass { public void outerDoSomething(){ final String localObj = "hello"; class InnerClass{ private String obj; public InnerClass(String obj) { this.obj = obj; } public void innerDoSomething(){ // do with obj } }; InnerClass innerObj = new InnerClass(localObj); } }荒唐原因:Java竟然允许内部类对象访问局部变量!
要知道局部变量的生命周期与局部内部类的对象的生命周期的不一致。局部变量当所处的函数执行结束后就已经死亡了,不存在了,但是局部内部类对象还可能一直存在(只要有人还引用该对象),这是就会出现了一个悲剧的结果,局部内部类对象访问一个已不存在的局部变量。
Java为了避免上述情况,才发明了上述机制,偷偷地将局部变量的引用放在内部类对象的成员变量中。
但是解决了生命周期的问题之后,又引出了另一个问题,因为局部变量和内部类中使用的变量是同一个对象吗?
比如下面的例子,而且如果不强制使用final,我们根本就不知道执行时,obj到底是哪个对象:
public class helloWorld { public void test() { String obj = "hello"; // 不使用final Thread myThread = new Thread() { public void run() { System.out.println(obj); // ojb到底是哪个? } }; myThread.start(); } public static void main(String [] argv) { helloWorld hello = new helloWorld(); hello.test(); } }又比如下面的例子:
public class helloWorld { public void test() { String obj = "hello"; // 不使用final Thread myThread = new Thread() { public void run() { } }; myThread.start(); System.out.println(obj); // obj到底是什么? } public static void main(String [] argv) { helloWorld hello = new helloWorld(); hello.test(); } }
相关文章推荐
- leetcode -- Rotate Image -- 要看有trick
- hive基本操作
- linux 备份策略
- LeetCode Longest Palindromic Substring
- CCF 201312-4 有趣的数(数位DP)
- CDH5.5上安装Rhadoop,RStudio server版初始化SparkR
- 【bzoj 4347】 [POI2016]Nim z utrudnieniem - 博弈论 DP
- 迭代法解题课后
- 文章标题
- Ajax帖子
- linux 系统登录日志
- RAC+单机组建dataguard
- python爬取返利网
- C/C++学习(六)线性表的插入、删除和查找
- python学习笔记-Day08--(面向对象)--补充
- linux 系统服务
- Application中的资源访问的三种方式
- css权威指南-基本视觉格式化(水平与垂直)
- linux 进程管理
- 关于信息增益和熵