黑马程序员技术交流社区

标题: 为什么 内部类 只能访问 外部类中被final修饰的局部变量该? [打印本页]

作者: First    时间: 2013-5-25 23:16
标题: 为什么 内部类 只能访问 外部类中被final修饰的局部变量该?
本帖最后由 First 于 2013-5-26 11:03 编辑

内部类访问外部类的局部变量, 此局部变量必须被final修饰

这是什么原因?

作者: 袁梦希    时间: 2013-5-25 23:22
本帖最后由 袁梦希 于 2013-5-25 23:36 编辑

刚才看错了,不好意思

作者: 王靖远    时间: 2013-5-25 23:34
这很难解释,涉及底层问题了。
简单来说就是为了防止你这个内部类所调用的局部变量因为非此内部类操作改变了值。
你想想外部类的一个局部变量不定义final。内部类A在用它,内部类A没有方法对这个变量操作,而外部类或者其他内部类操作了它改变了数值,那么对内部类A来说不是很郁闷吗。。。内部类A根本没有操作它却改变了数值。
作者: 袁梦希    时间: 2013-5-25 23:37
楼主刚才看错了  不好意思
作者: First    时间: 2013-5-25 23:48
王靖远 发表于 2013-5-25 23:34
这很难解释,涉及底层问题了。
简单来说就是为了防止你这个内部类所调用的局部变量因为非此内部类操作改变 ...

虽然这么说,
但是 即使内部类没有去改变 这个局部变量的值 却被外部类改变了 也不会发生安全问题或其他问题吧?
既然这样,即使是被外部改变了 对于程序而言 是不是也没什么关系呢?

要是这样的话,为何还要用 final 修饰呢?
作者: First    时间: 2013-5-25 23:52
袁梦希 发表于 2013-5-25 23:22
刚才看错了,不好意思

我提问符号规范我就安心了

多谢版主了
作者: 杨青    时间: 2013-5-25 23:58
生命周期不同啊。当方法结束时,方法中的局部变量会被释放掉,final保证这个变量始终指向一个对象,内部类就可以大胆直接指向该对象.
作者: 杨青    时间: 2013-5-25 23:58
生命周期不同啊。当方法结束时,方法中的局部变量会被释放掉,final保证这个变量始终指向一个对象,内部类就可以大胆直接指向该对象.
作者: 王靖远    时间: 2013-5-25 23:59
First 发表于 2013-5-25 23:48
虽然这么说,
但是 即使内部类没有去改变 这个局部变量的值 却被外部类改变了 也不会发生安全问题或其他 ...

会有安全问题啊。这个局部变量内部类要拿来用,假设本来是a ,内部类想用的也是a就拿来用了,这时候外部类方法有a++的操作,那么这个内部类拿来用的就不是a了,违背了本意。这就是安全隐患。所以必须要用final。
作者: 杨青    时间: 2013-5-25 23:59
方法中的局部变量,方法结束以后这个变量就要被释放掉.final保证这个变量始终指向一个对象,内部类就可以大胆直接指向该对象.
作者: 杨青    时间: 2013-5-25 23:59
方法中的局部变量,方法结束以后这个变量就要被释放掉.final保证这个变量始终指向一个对象,内部类就可以大胆直接指向该对象.
作者: 陈潜    时间: 2013-5-26 00:16
这个问题,前几天刚刚问过的。
1、内部类不是直接调用方法中的参数,而是通过复制到了自己内部,调用的是自己内部的那个参数,也因为如此,导致内部类修改这个参数的时候只改变了自己的参数,而方法中那个局部变量没有改变,为了保持一致性,使用final。
2、二者的生命周期不一样,为了防止方法结束局部变量销毁,而导致内部类无法访问,使用final。
作者: First    时间: 2013-5-26 00:44
王靖远 发表于 2013-5-25 23:59
会有安全问题啊。这个局部变量内部类要拿来用,假设本来是a ,内部类想用的也是a就拿来用了,这时候外部 ...

对于你的回答, 我有点不太理解,能不能请你写个代码例子
非常感谢
作者: 张旺达    时间: 2013-5-26 10:27
内部类定义在局部时

1,不可以被成员修饰符修饰

2,可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。下面是一个例子:
  1. class Outer
  2. {
  3. void method()
  4. {
  5. int y = 4;
  6. class Inner
  7. {
  8. void function()
  9. {
  10. System.out.println(y);
  11. }
  12. }
  13. new Inner().function();
  14. }
  15. }

  16. class InnerClassDemo
  17. {
  18. public static void main(String[] args)
  19. {
  20. new Outer().method();
  21. }
  22. }
复制代码

QQ截图20130526102536.png (3.82 KB, 下载次数: 0)

1

1

作者: 张旺达    时间: 2013-5-26 10:28
需要声明为最终类型嘛,记住就行了
作者: First    时间: 2013-5-26 11:00
陈潜 发表于 2013-5-26 00:16
这个问题,前几天刚刚问过的。
1、内部类不是直接调用方法中的参数,而是通过复制到了自己内部,调用的是自 ...

你的解答给了我很大的起发。谢谢。
作者: First    时间: 2013-5-26 11:02
  1. public class Demo{

  2.         public static void main(String[] args) {
  3.                 int x = 1;
  4.                
  5.                 Object c = new Fin().getC();//c引用了局部内部类对象。
  6.                 System.out.println(c.toString());
  7.         }
  8.        
  9. }

  10. class Fin{
  11.         int x = 0;
  12.        
  13.         class In{
  14.                 public void showX(){
  15.                         System.out.println(x);
  16.                 }
  17.         }
  18.        
  19.         public Object getC(){
  20.                 final int y = 1;//如果 这里的 y 没有被final 修饰
  21.                 //在内部类Inner 中就可以出现 y = y+1;
  22.                
  23.                 //Inner in = new Inner();
  24.                 class Inner{
  25.                         int z = 5;
  26.                         public int showY(){
  27.                                 //y = y +1;
  28.                                 System.out.println(y);
  29.                                 x = x +1;
  30.                                 return x; //之所以可以引用外部类的成员,是因为在使用getC方法时
  31.                                 //必须先创建外部类Fin的对象。
  32.                         }
  33.                        
  34.                         public String toString(){
  35.                                 System.out.println("reachable?");
  36.                                 return (y+z+showY())+"";
  37.                         }
  38.                 }
  39.                
  40.                 Inner in = new Inner();
  41.                
  42.                 in.showY();
  43.                
  44.                 return in;
  45.                 //因为getC返回Inner对象,
  46.                 //该对象被其他外部类的参数引用,所以当getC 生命周期结束时,
  47.                 //Inner 对象的生命周期没有结束。(第9行 被 c 引用). 因此 y的生命周期已经结束
  48.                 //Inner 要使用y的值就必须 把y 复制到 它的对象中,而不能直接引用。
  49.                 //所以变量 y 的值是不能在内部类中被赋值的, 即 y = y + 1;这样的操作不会把 y的 赋值为 2;
  50.                 //所以为了表明这种操作不成立,或为了避免这样的操作,就必须保证y 是不可变的,即
  51.                 //y 的值要用final修饰。
  52.         }
  53. }
复制代码
最后贴下自己的理解,有不对的地方还请给我指正。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2