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