为什么匿名内部类和局部内部类只能访问final变量

是变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final。

一个xx.java类里面有匿名内部类,编译出来的class文件会有xx.class 、xx$1.calss...
例如:

public class InnerClass {

 public static void test(final String s){            
     InnerClass c = new InnerClass(){ 
         public void m(){ 
             int x = s.hashCode();   
             System.out.println(x);  
         } 
    };  
 }
}

编译出来的两个class文件是:InnerClass.class和 InnerClass$1.class,代码分别如下:

package smartpush;

import java.io.PrintStream;

public class InnerClass
{
  public static void test(String s)
  {
    InnerClass c = new InnerClass(s) {
      public void m() {
        int x = this.val$s.hashCode();
      System.out.println(x);
  }
 };
}
}

package smartpush;

import java.io.PrintStream;

class 1 extends InnerClass
{
  public void m()
{
  int x = this.val$s.hashCode();
  System.out.println(x);
}
}

这说明虽然匿名内部类在方法的内部,但实际编译的时候,内部类会编译成一个inner_object,而外部类中的方法中的变量s只是方法的局部变量,s的作用域只在这个方法内部有效。查看反编译出来的源码,内部类 class 1

int x = this.val$s.hashCode();

内部类使用this.val$s引用了方法内部的变量s

对于一个final变量:
如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;
如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

因此内部类要引用变量s,编译器就要保证s的引用 this.val$s在初始化后就不能再改变。
不然如果在内部类的方法执行前,s的引用指向了其他地方,例如
s="321"

这样匿名类的变量指向B而外部的变量却指向A了,这结果显然是不能接受的
于是为了保证变量引用的一致性,内部类只能访问final变量。

http://stackoverflow.com/questions/3910324/why-java-inner-classes-require-final-outer-instance-variables
http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-differen
http://feiyeguohai.iteye.com/blog/1500108
http://blog.csdn.net/woshichunchun/article/details/7925823
http://blog.csdn.net/axman/article/details/1460544

你可能感兴趣的:(为什么匿名内部类和局部内部类只能访问final变量)