基本同意 @小小码农努力学习 ,但其实并不能说是去掉了限制,可以说这是一颗语法糖的语法糖而已,因为对于 JVM 而言,并没有内部类和外部类的概念,只是两个字节码文件 Outer.class 和 Outer$Inner.class。
还原一下语法糖的内幕:
public class Outer{//外部类Outer
void show(){
final int num =10;//局部变量num
//局部内部类Inner
class Inner{
private final int val$num;
private final Outer this$0;
public Inner(Outer outer,int num){
val$num = num;
this$0 = outer;
}
void dosomething(){
System.out.println(num);//局部内部类也能访问非final修饰的局部变量吗?
}
}
new Inner(this,num).dosomething();
}
}
看懂上面的代码就知道为什么我们可以访问外部类的成员变量和方法体的局部变量(当然私有成员还需要在外部类添加相应的类似 get() 方法的语法糖,这里不探讨。)因为方法体的局部变量在内部类中会拷贝成内部类的成员变量,即并不是同一个内存区域(废话,局部变量是在栈中分配的,而类的成员变量是在堆中分配的),为了保持两者一致性,就只能限制他们初始化之后不能修改。
至于 JDK 1.8 加的语法糖就更简单了,就是自动加了一下 final,所以下面的代码还是编译不通过的。
public class Outer{//外部类Outer
void show(){
int num =10;//局部变量num
//局部内部类Inner
class Inner{
void dosomething(){
System.out.println(num);//局部内部类也能访问非final修饰的局部变量吗?
}
}
num = 11;
new Inner().dosomething();
}
}