通俗地解释为什么Java中局部内部类引用外部类的局部变量必须是final修饰的
首先上一段代码(一言不合就上代码)
public class AreaOuter {
private int cnt = 1;
public void show() {
// 局部变量,java8开始,如果该变量被内部类引用,java编译器就会默认给该变量加final修饰。
// 所以,如果该变量需要被内部类引用,虽然可以省略final,但是在实际开发中最好还是加上final。
// 如果没有被内部类引用,那么java编译器就不会做处理。
int ib = 2;
// 局部内部类
final class AreaInner {
private int ia = 1;
public AreaInner() {
System.out.println("局部内部类的构造方法");
}
public void test() {
// 如果用到外部的变量ib,则ib为final修饰的
System.out.println("ib = " + ib);
System.out.println("ia = " + ia);
System.out.println("cnt = " + cnt);
}
}
//调用方法:只能在方法体内部调用,声明局部内部类的引用指向局部内部类的对象
AreaInner areaInner = new AreaInner();
areaInner.test();
}
}
再来解释为什么
首先给出一个结论:生命周期不一致。
局部变量ib和内部类AreaInner都是在show方法中声明的,其生命周期在调用show方法之后就结束了。但是,局部变量ib是优先于局部内部类AreaInner声明的,所以局部变量ib的生命周期要长一点。在局部内部类AreaInner引用局部变量ib的时候,实际上会将ib的值拷贝一份拿到内部类使用。
这个时候就可能产生一个问题,什么问题呢?假如我在局部内部类AreaInner引用局部变量ib之后,背着AreaInner把ib的值给改变了,结果AreaInner还在傻乎乎地按照改变之前的值运行程序,最终就会导致运行结果出现差错。
所以为了防止这种情况发生,java编译器就会在局部变量的前面加上final修饰。这样一来,ib的值改不了,那么最后局部内部类引用局部变量运行的结果也就不会出现差错。