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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 左建飞 中级黑马   /  2012-7-27 22:50  /  3167 人查看  /  8 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 左建飞 于 2012-7-28 10:39 编辑
  1. class Outer
  2. {
  3.   int x=3;
  4.   void method()
  5.     {
  6.        final int y=4;//此处为局部变量
  7.        class Inner
  8.          {
  9.             void funnction()
  10.               {
  11.                  System.out.println(x);
  12.                  System.out.println(y);//局部内部类要访问局部变量,局部变量必须是final修饰的。为什么?
  13.               }
  14.         }
  15.         new Inner().funnction();
  16.     }
  17. }
复制代码
局部内部类要访问局部变量局部变量必须由final修饰,为什么?

评分

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

查看全部评分

8 个回复

倒序浏览
1.内部类可以直接访问外部类的private field,这打破了类的封装。但是内部类又有它自身的好处,比如简洁,可见性等,于是就把它定位成“只读”,也就是final。
2.局部内部类  访问   局部变量 时,那个变量必须是final的。因为可以通过enclosing class访问那个局部变量 ,也可以通过   内部类  访问,可能造成问题,所以就必须是final的
3.变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final。因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或参数的作用域只在这个方法内部有效。因为编译的时候内部类和方法在同一级别上,所以方法中的变量或参数只有为final,内部类才可以引用
回复 使用道具 举报
方法中的内部类访问局部变量的时候,局部变量需要被 final 关键字修饰。因为方法中的代码是由上而下顺序执行的,方法运行结束后,局部变量就被销毁,内部类的生命周期可能会比局部变量的生命周期长;看下面的代码,方法中的内部类 Inner.class 调用方法中的局部变量 x ,正常调用的时候内部类能够调用到方法中的局部变量,并将内部类对象 inner 返回,正常调用结束后,如果方法中的局部变量 x 没有被 final 关键字修饰,x 则会被销毁,我们再通过反射的方式去调用 x 的时候则会发现找不到变量 x ,如果局部变量 x 被 final 关键字修饰后,则 x 在方法运行结束后不会被销毁,而是常驻在内存中直到 JVM 退出,这样再通过反射调用的时候依然可以找到 x 。

点评

提醒李珍同学:如果觉得资料比较好,需要引用该资料,请附上资料来源地址,否则将认为是抄袭。(警告1次)  发表于 2012-7-28 00:39
回复 使用道具 举报
内部类使用的变量是编译器定义的一个同类型变量,并给该变量赋值。
必须是final修饰主要为了防止内部类对变量的改动
回复 使用道具 举报
本帖最后由 陈欢 于 2012-7-27 23:48 编辑

其实就是一个变量作用域的问题。因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final。因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或参数的作用域只在这个方法内部有效。因为编译的时候内部类和方法在同一级别上,所以方法中的变量或参数只有为final,内部类才可以引用。

说的更直白点,如果不是final的局部变量,你的方法结束了就没了。
但是你的内部类却不是和你的方法同时执行的, 当你事件发生的时候才会执行,这时你的方法已经结束了,那到哪里去找这个局部变量呢?那么这个就不能用了。


点评

谢谢你的回答,明白了很多。^_^  发表于 2012-7-28 10:36

评分

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

查看全部评分

回复 使用道具 举报
final修饰后,编译器是这样处理内部类的。如果这个外部局部变量是常量,则在内部类代码中直接用这个常量。如果是类的实例,则编译器将产生一个内部类的构造参数,将这个final变量传到内部类里,这样即使外部局部变量无效了,还可以使用。

内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。
这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是 final来规避这种莫名其妙错误的存在。

点评

很清楚明了,谢谢你,同学。^_^  发表于 2012-7-28 10:37
回复 使用道具 举报
陈欢 发表于 2012-7-27 23:32
其实就是一个变量作用域的问题。因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者 ...

有点明白了
回复 使用道具 举报
局部内部类访问了跟他同级别的局部变量,如果这个变量没有被final修饰,也就是没有变成全局常量的话,类的生命周期大于局部变量的周期会造成无法访问的后果。
回复 使用道具 举报
因为这个内部类存在于方法内
方法内的局部变量虽说作用域是方法体内
但是它所包含的内部类却不是与方法共存亡的
所以当方法执行完毕,方法的内存被释放
而这个内部累还在使用该方法的一个不存在的局部变量是不合常理的
所以,被final修饰后值是不可变的,所以即便方法不存在了
那个值还是可以拿来继续使用。
也可以换个理解方式,那就是我们不是为了给内部类使用才把局部变量用final修饰
而是被final修饰的,才有资格被内部类使用。
希望可以对你有所帮助。。。

点评

还有同学,你可以教教我在线0小时,技术分16的诀窍么。眼馋呀。  发表于 2012-7-28 10:44
忒有帮助了,谢谢你,同学。  发表于 2012-7-28 10:39

评分

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

查看全部评分

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