本帖最后由 聂斌 于 2013-3-14 01:41 编辑
内部类不能访问外部类方法中的局部变量,除非变量是final的(一般发生在方法中定义的内部类)。这是因为局部变量的生命周期原因。
public class Outer {
int x = 3;
void method(final int a) // 这里必须得加final ,不然不能访问这个a,因为这个a是个变量,,不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。这个a不在对象中,他是局部变量,
{
final int y = 4;
class Inner
{
void function()
{
System.out.println(a); //从内部类中访问局部变量y,那么这个y就得被声明为final
}
}
new Inner().function();
}
那么为什么那个局部变量y 或者a一定得被final修饰呢???根本原因出在局部变量的生命周期,,,
1..内部类对象的生命周期会超过局部变量的生命期。
局部变量的生命期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,就退栈,这些局部变量全部死亡。而内部类对象生命期,与其它类一样,当创建一个局部内部类对象后,只有当没有其它人再引用它时,它才会死亡。所以完全可能一个方法已调用结束(局部变量已死亡),但该局部类的对象仍然活着。即:局部类的对象生命期会超过局部变量。
2....局部内部类的对象能访问同一个方法中的局部变量,那么这就要求局部内部类对象还活着,那么栈中的那些它要访问的局部变量就不能“死亡”(否则:它都死了,还访问个什么呢?)。这就是说:局部变量的生命期至少等于或大于局部内部类对象的生命期。
3...解决方法:
把一个方法l的局部变量定义为fina 。定义为final后,jvm会将局部内部类对象要访问的final型局部变量都拷贝一份,,那个这个复制品就成为该内部类对象中的一个数据成员。这样,即使栈中局部变量已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,照样可以访问final型局部变量。,,,也就是说:局部内部类对象中包含有要访问的final型局部变量的一个拷贝,成为它的数据成员。所以当一个方法结束后,,那么方法里面的局部变量就全死亡了。但是局部内部类对象中有final型局部变量的拷贝。
顺便解释下为什么局部内部类对象中有局部变量的拷贝。
在上面代码中,局部内部类并不是直接使用方法传进来的参数a,而是内部类将传进来的参数a通过自己的构造器备份到了自己的内部,自己内部的方法function() 调用的实际是自己的属性而不是外部类方法的参数a。
这样理解就很容易得出为什么要用final了,如果内部类修改了参数a的值,,那么也不可能影响到原参 数,也就是我们在内部类中改掉参数的值,但是外部调用的时 候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以java就把内部类使用的局部变量设定为 final来规避这种莫名其妙情况的存在。当a被final修饰后,那么这个a就是常量了,,,局部内部类里面就不能修改这个a了,,只能使用这个a,因为常量a只能被赋值一次,,,
|