A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 晓风 于 2014-8-12 09:27 编辑

之前看视频的时候也有疑问,自己虽然知道个中原因,但确不能够很好的说明。
后来在论坛里也有同学提问过,看过了回复。可还不是很明了。自己也查了资料。
以下是自己综合各方面的一些总结:
在java中, 方法的内部类可以访问方法中的局部变量,但必须用final修饰才能访问。
原因:
   一, 当方法被调用运行完毕之后,局部变量就已消亡了。但内部类对象可能还存在,
           直到没有被引用时才会消亡。此时就会出现一种情况,就是内部类要访问一个不存在的局部变量。
                        
   二,解决这一问题的办法就是使用final修饰局部变量,通过将final局部变量"复制"一份,
         复制品直接作为方法内部类中的数据成员,这事方法内部类访问的其实是这个局部变量的复制品!
         而且,由于被final修饰的变量赋值后不能再修改,所以就保证了复制品与原始变量的一致。
                        
    三,原因二的功能能实现的原因是:Java采用了一种copy   local   variable(复制局部变量)的方式来实现,
            也就是说把定义为final的局部变量拷贝过来用,而引用的也可以拿过来用,只是不能重新赋值。
            从而造成了可以access   local   variable(访问局部变量)的假象,而这个时候由于不能重新赋值,
             所以一般不会造成不可预料的事情发生。
                        
     四, 使用final修饰符不仅会保持对象的引用不会改变,
            而且编译器还会持续维护这个对象在回调方法中的生命周期.
            所以这才是final变量和final参数的根本意义.

评分

参与人数 2技术分 +1 黑马币 +5 收起 理由
QQ605586042 + 5
格子、 + 1 赞一个!

查看全部评分

24 个回复

正序浏览
通顺了,多谢
回复 使用道具 举报
忧伤-hy 发表于 2015-8-26 17:55
再说了,生命周期的问题,你一个方法内部类只有在方法里创建对象,然后再通过外部类的对象调用方法才能够使 ...

如果考虑到多线程的话你就会好理解了假如类中有如下方法
public void execute() {
                final int a = 10;
                class Desk {
                        public void execute() {
                                new Thread() {
                                        @Override
                                        public void run() {
                                                try {
                                                        Thread.currentThread().sleep(2000);
                                                        System.out.println(a);
                                                } catch (final InterruptedException e) {
                                                        e.printStackTrace();
                                                }
                                        }
                                }.start();
                        }
                }
                new Desk().execute();
                System.out.println("主方法已经over");
        } 在主线程方法执行结束后,内部类里面的方法还在运行
回复 使用道具 举报
总结的很全面,厉害!!!
回复 使用道具 举报
不错不错
回复 使用道具 举报
感谢,受教了
回复 使用道具 举报
不错不错 学习了
回复 使用道具 举报
都好好努力学习吧
回复 使用道具 举报
弄懂了点点
回复 使用道具 举报
很有用学到知识了
回复 使用道具 举报
第一点中,如何去引用一个已经消亡的方法中的内部类对象?如果没有办法引用的话,这个对象就会在某个时刻被回收,自然,局部变量可以不用定义为final
回复 使用道具 举报
没代码说明!!!,差评
回复 使用道具 举报
学习学习
回复 使用道具 举报
正好存在疑问呢。谢谢楼主的讲解
回复 使用道具 举报
asinzuo 来自手机 中级黑马 2015-8-27 17:07:41
12#
晓风 发表于 2014-8-11 22:17
之前看视频的时候也有疑问,自己虽然知道个中原因,但确不能够很好的说明。
后来在论坛里也有同学提问过, ...

说的好有道理
回复 使用道具 举报
再说了,生命周期的问题,你一个方法内部类只有在方法里创建对象,然后再通过外部类的对象调用方法才能够使用内部类,当方法调用完了,内部类也不可能再被访问到了吧,照理内部类对象也应该成为了垃圾。好像当方法消失后内部类还有作用似得。
必须加final修饰变量,把变量变成常量,延长生命周期的同时也限制了该变量的用途,甚至可以说完全导致变量失去意义,变量不就是因为可以存储不断变化的数据才被声明,就好比人为了长寿,把自己变成石头一样
反正我是很不明白这样设计有什么用处
回复 使用道具 举报 1 0
这个问题真的很闹心,在我看来内部内的意义就是在于更方便的访问外部类的成员属性和成员方法,而为何要更进一步声明在方法内,不就是为了访问方法的局部变量吗?然后,好好的变量却变成了final修饰的常量,这就失去了如此设计的初衷
回复 使用道具 举报
谢谢 正在查找这部分内容 楼主总结的很详细 只是我想问下 被final修饰的局部变量的生命周期是什么? 比如在main方法中的被final修饰变量  是jvm退出运行后才消失(是不是和static修饰的变量生命周期一样? 随着类的消失而消失?) 还是访问它的局部匿名对象不再使用它的时候消失? 请详细解答下 谢谢
回复 使用道具 举报
黑马TYR 来自手机 中级黑马 2015-4-13 17:04:25
8#
不是很清晰
回复 使用道具 举报
马上要看这一块
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马