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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

如下图,为啥一定要final 修饰,让局部变量进入常量池呢?视频老师给的解释是,当调用这个方法时,方法弹栈,这个局部变量也会消失,局部内部类对象想去调用这个变量时,这个局部变量已经消失了。可是,在调用的时刻,方法还没弹栈啊,局部变量还在的啊。我的理解如下图,请问下论坛各位大神,为啥print()方法无法访问num呢?

QQ图片20160813164533.png (22.67 KB, 下载次数: 20)

QQ图片20160813164533.png

QQ图片20160813165212.png (185.05 KB, 下载次数: 25)

QQ图片20160813165212.png

5 个回复

倒序浏览
兄弟,这个问题我也考虑过。你可以参考相关博客,我的一些看法如下,供参考。
如果局部内部类访问非final变量,编译器在编译时就会出现报错,说明这个问题与Java的内部类的编译机制有关系。实际上,内部类在编译时Java虚拟机就把局部变量的副本值传递复制了一份给内部类,复制的原因如下:
局部内部类对象生命周期和局部变量不同,有可能局部方法结束后(局部变量也销毁后)局部内部类对象还存在,为防止此情况发生,局部内部类对象创建时会拷贝一份局部变量。
也就是说如果在方法中,局部变量进行更改的话,局部内部类是不知道变量变化了的,它存储的值还是之前的拷贝值。因此为了保持局部变量和拷贝数据一致性,需要使用final限定,拷贝后不变,保持一致性。
比如说你把num的值改为了20,但是局部内部类中存储的还是编译时期的10,这样子就会数据不一致,跟你的需求产生矛盾,事实上也可以称作一个错误。JAVA是一种强类型的语言,编译器会把许多问题在编译时暴露出来,因此这种情况是绝对不允许出现在运行的时候,所以在编译期间就会对强制要求内部类里面的变量必须使用final修饰。使用final修饰后,变量不允许变化,确保数据的一致性,才可以编译通过。

评分

参与人数 1黑马币 +3 收起 理由
r1503882525 + 3 回答认真,赞一个

查看全部评分

回复 使用道具 举报
另外补充一句,JDK1.8之后,局部内部类会将访问到的局部变量自动加上final进行修饰。在JDK1.8上,你上面的程序是OK的,num会自动加上final。但是如果你使用num++的话,编译器就会报错,因为final变量不能被重新赋值。
回复 使用道具 举报
aliali007 发表于 2016-8-13 18:20
另外补充一句,JDK1.8之后,局部内部类会将访问到的局部变量自动加上final进行修饰。在JDK1.8上,你上面的 ...

JDK1.8 能自动加上Final。。 这个了解。 但是,我想问的不是他会不会加final。 我想问的其实是,为什么要加final。  为啥只能访问常量池的
回复 使用道具 举报
aliali007 发表于 2016-8-13 18:15
兄弟,这个问题我也考虑过。你可以参考相关博客,我的一些看法如下,供参考。
如果局部内部类访问非final变 ...

噢 。感谢。。认真看了你的解答。~了解!谢谢大牛啦~
回复 使用道具 举报
局部变量的生命周期与局部内部类的对象的生命周期是不一样的。局部变量当所处的函数执行结束后就已经死亡了,但是局部内部类对象还可能一直存在(只要有人还引用该对象),这是就会出现局部内部类对象访问一个已不存在的局部变量,所以才使用final修饰.
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马