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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 苗润 中级黑马   /  2014-6-7 14:18  /  1691 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 苗润 于 2014-6-7 22:09 编辑

在内部类中访问外部类局部变量的时候,为什么一定把变量修饰为final
请说的清楚些,说些原理

6 个回复

倒序浏览
好好看书,看视频
回复 使用道具 举报 1 0
局部变量的生命周期与局部内部类的对象的生命周期的不一致性!
假如方法f被调用,从而在它的调用栈中生成了变量i,此时产生了一个局部内部类对象inner_object,它访问了该局部变量i .当方法f()运行结束后,局部变量i就已死亡了,不存在了.但:局部内部类对象inner_object还可能   一直存在(只能没有人再引用该对象时,它才会死亡),它不会随着方法f()运行结束死亡.这时:出现了一个"荒唐"结果:局部内部类对象inner_object要访问一个已不存在的局部变量i!
当变量是final时,通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量时,其实真正访问的是这个局部变量的"复制品"(即:这个复制品就代表了那个局部变量).因此:当运行栈中的真正的局部变量死亡时,局部内部类对象仍可以访问局部变量(其实访问的是"复制品"),给人的感觉:好像是局部变量的"生命期"延长了.
当变量是final时,若是基本数据类型,由于其值不变,因而:其复制品与原始的量是一样.语义效果相同.(若:不是final,就无法保证:复制品与原始变量保持一致了,因为:在方法中改的是原始变量,而局部内部类中改的是复制品)。

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1 赞一个!

查看全部评分

回复 使用道具 举报 2 0
加上final的局部变量,在javac编译的时候,会把这个变量提升为和类属性同级的变量,也就是说这个变量不是在执行栈里,而是在外部对象的堆中保存。而栈只是放临时的变量。这样就可以通过外部对象的this来引用到了。总之被final修饰的局部变量会隐形的提升为成员变量。
回复 使用道具 举报 0 1
万马奔腾 发表于 2014-6-7 15:15
局部变量的生命周期与局部内部类的对象的生命周期的不一致性!
假如方法f被调用,从而在它的调用栈中生成了变 ...

懂了~谢谢,不过关于隐形提升的说法呢? final修饰的变量会隐形提升等级 就是3L的说法
回复 使用道具 举报
在JVM编译的过程中,它会把被final修饰的变量值直接赋给.class文件中。也就是说.class中相应的位置该变量就是被赋的具体值。
不存在类型提升的说法,如果真的提升了,那就没有局部跟着方法走这一说了...
不信你可以做这样一个例子:
class Outer{
        public void show(){
          final int x = 3;
          class Inner {
                  public void abc(){
                    System.out.println("Inner...abc"+x);   //编辑结束后这个x的值在相应的.class文件里就是3
                  }
           }
          new Inner().abc();
        }
}

class InnerClassDemo3 {
        public static void main(String[] args)
        {
                new Outer().show();
        }
}

回复 使用道具 举报
idency 高级黑马 2014-6-10 22:00:01
7#
:handshake
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马