首先举一个匿名内部类的例子:
class Outer{
public Inner getInner(String name){
return new Inner(){
//name = name+" ";编译错误,这里用来示例
public void printf(){
System.out.println(name);
}
};
}
}
1.外部的局部变量传递到内部类中,实际上是将局部变量复制了一份之后,复制品直接作为局部内部类(匿名类也是一种局部内部类)的数据成员,内部类并不直接操作外部的局部变量,而是访问这个复制品(即:这个复制品就代表了局部变量)。因为局部变量的生命周期在方法调用之后就结束了,但内部类的生命周期在方法调用之后还没有结束,只有在内部类引用完全不被使用之后才会由垃圾回收处理。
但是从语义上来看,似乎
当变量是final时,通过将final局部变量”复制”一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量 时,其实真正访问的是这个局部变量的”复制品”(即:这个复制品就代表了那个局部变量)
上面那份代码相当于(实际上更复杂一些,但大致相当于这个原理):
public class Outer{
public Inner getInner(final String name){
return new Outer$1(name);
class Outer$1 implements Inner{
Outer$1(String name) {
this.name = name;
}
public void printf(){
System.out.println(this.name);
}
}
}
}
如果在内部类中操作name,实际上操作的是nane的复制品,对原有的局部变量并不会产生影响。如果不加final,就会编译成如下样子
public class Outer{
public Inner getInner(final String name){
return new Outer$1(name);
class Outer$1 implements Inner{
Outer$1(String name) {
this.name = name;
this.name = this.name + " ";
}
public void printf(){
System.out.println(this.name);
}
}
}
}
但是从语义语法上来看:
class Outer{
public Inner getInner(String name){
return new Inner(){
name = name+" ";
public void printf(){
System.out.println(name);
}
};
}
}
局部变量发生了改变,客户端并不会意识到内部类修改的只是局部变量的复制品。所以为了防止这种语义语法上的不一致,强行规定传递给局部内部类的变量必须是final