先看一下Java对匿名内部类访问外部类局部变量的处理
public class Test {
public void fun() {
final Data data = new Data();
data.id = 0;
new Test() {
public void innerFun() {
data.id = 1;
}
}.innerFun();
}
}
上面 这段代码编译成两个class文件(一个.java文件中有几个类就会编译出几个.class文件)
匿名内部类是这样的
class Test$1 extends Test {
final /* synthetic */ Test this$0;
final /* synthetic */ Data val$data;
Test$1(Test this$02, Data data) {
this.this$0 = this$02;
this.val$data = data;
}
public void innerFun() {
this.val$data.id = 1;
}
}
外部类是这样的
public class Test {
public void fun() {
Data data = new Data();
data.id = 0;
new Test$1(this, data).innerFun();
}
}
可以看到,外部类以及被访问的局部变量会通过构造函数传进去,对于局部变量,内部类使用的引用和外部类使用的并不是同一个,而如果局部变量不是final的话,当其中一方对其重新赋值就会导致内部类和外部类的数据不同步,大概就是像下面这种,结果会输出false,所以要声明成final
Data data = new Data();
Data data1 = data;
data = new Data();
System.out.println(data == data1);
关于外部类的全局变量为什么不用声明为final,是因为在内部类中是通过this来访问的,这个和外部类是同一个引用