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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 聂益飞 高级黑马   /  2013-3-13 19:40  /  1528 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 黄玉昆 于 2013-3-15 22:00 编辑

内部类定义在局部中,只能访问该局部中的常量,被final修饰  为什么是这样?

点评

如果问题已经解决了,请将分类改为已解决;一定要对别人的回答有相应的回复哦,谢谢  发表于 2013-3-15 08:35

评分

参与人数 1黑马币 +12 收起 理由
黄玉昆 + 12 这问题已经问好多了,请直接搜final相关的.

查看全部评分

8 个回复

倒序浏览
可以贴下代码么?
回复 使用道具 举报
我想你想问的是:内部类定义在局部时,是不可以访问它所在的局部中的变量,除非是访问被final修饰的局部变量。
毕老师视频里演示了,局部变量不定义成final的话编译会失败,所以你要在局部内部类里访问,只能将局部中的变量修饰成final类型。
回复 使用道具 举报
本帖最后由 崔芝鲁 于 2013-3-13 23:00 编辑

定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制,可以声明为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现特定的接口。static的内部类行为上象一个独立的类,非static在行为上类似类的属性或方法且禁止声明static的方法。内部类可以访问外部类的所有方法与属性,但static的内部类只能访问外部类的静态属性与方法。
内部类可以声明在外部类的方法中或语句块中。如果内部类需要访问包含它的外部类方法或语句块的局部变量或参数,则该局部变量或参数必须是final的。外部类的其他方法、其他类无法访问声明在方法内部或块内部的内部类。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
这里有一篇博客贴出来,大家一起研究一下,大体意思说的是方法与类的存活的时间不一样,
方法执行完了,但类仍可以存在,这时方法里定义的一些非final的变量已经找不到了,因此只能定义成final的,
这是我的理解,呵呵

http://blog.csdn.net/salahg/article/details/7529091
回复 使用道具 举报
你到底想说什么,大哥。
回复 使用道具 举报
小路飞 来自手机 中级黑马 2013-3-14 00:58:47
7#
final修饰的变量存放在方法区中的常量池中,内部类可以随时访问,即使堆内存中的对象被回收了,也是现学现卖,呵呵,一起加油!
回复 使用道具 举报
追究根本原因其实就是作用域中变量的生命周期导致的。

首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。问题就来了,如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。参考:http://blog.csdn.net/woshichunchun/article/details/7925823

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
聂斌 中级黑马 2013-3-14 01:37:19
9#
本帖最后由 聂斌 于 2013-3-14 01:41 编辑

内部类不能访问外部类方法中的局部变量,除非变量是final的(一般发生在方法中定义的内部类)。这是因为局部变量的生命周期原因。
public class Outer {

        int x = 3;

        void method(final int a)   // 这里必须得加final ,不然不能访问这个a,因为这个a是个变量,,不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。这个a不在对象中,他是局部变量,
        {
               
                final int y = 4;
                class Inner
                {
                        void function()
                        {
                                System.out.println(a); //从内部类中访问局部变量y,那么这个y就得被声明为final
                        }
                }
        
                new Inner().function();
               
        }


那么为什么那个局部变量y 或者a一定得被final修饰呢???根本原因出在局部变量的生命周期,,,

1..内部类对象的生命周期会超过局部变量的生命期。
局部变量的生命期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,就退栈,这些局部变量全部死亡。而内部类对象生命期,与其它类一样,当创建一个局部内部类对象后,只有当没有其它人再引用它时,它才会死亡。所以完全可能一个方法已调用结束(局部变量已死亡),但该局部类的对象仍然活着。即:局部类的对象生命期会超过局部变量。

2....局部内部类的对象能访问同一个方法中的局部变量,那么这就要求局部内部类对象还活着,那么栈中的那些它要访问的局部变量就不能“死亡”(否则:它都死了,还访问个什么呢?)。这就是说:局部变量的生命期至少等于或大于局部内部类对象的生命期。

3...解决方法:
把一个方法l的局部变量定义为fina 。定义为final后,jvm会将局部内部类对象要访问的final型局部变量都拷贝一份,,那个这个复制品就成为该内部类对象中的一个数据成员。这样,即使栈中局部变量已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,照样可以访问final型局部变量。,,,也就是说:局部内部类对象中包含有要访问的final型局部变量的一个拷贝,成为它的数据成员。所以当一个方法结束后,,那么方法里面的局部变量就全死亡了。但是局部内部类对象中有final型局部变量的拷贝。

顺便解释下为什么局部内部类对象中有局部变量的拷贝。
在上面代码中,局部内部类并不是直接使用方法传进来的参数a,而是内部类将传进来的参数a通过自己的构造器备份到了自己的内部,自己内部的方法function() 调用的实际是自己的属性而不是外部类方法的参数a。
这样理解就很容易得出为什么要用final了,如果内部类修改了参数a的值,,那么也不可能影响到原参 数,也就是我们在内部类中改掉参数的值,但是外部调用的时 候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以java就把内部类使用的局部变量设定为 final来规避这种莫名其妙情况的存在。当a被final修饰后,那么这个a就是常量了,,,局部内部类里面就不能修改这个a了,,只能使用这个a,因为常量a只能被赋值一次,,,




评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马