黑马程序员技术交流社区

标题: final与内部类的小问题 [打印本页]

作者: 赵家阳    时间: 2013-3-5 15:50
标题: final与内部类的小问题
本帖最后由 赵家阳 于 2013-3-7 10:32 编辑

“内部类定义在类中的局部位置上时,只能访问该局部被fianl修饰的局部变量”这句话怎么理解???
作者: 李洪因    时间: 2013-3-5 16:24
首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并不与外部类在同一class文件中。
当外部类传的参数被内部类调用时,从java程序的角度来看是直接的调用例如:
public void dosome(final String a,final int b){
class Dosome{public void dosome(){
System.out.println(a+b)
}};
Dosome some=new Dosome();
some.dosome();
}
从代码来看好像是那个内部类直接调用的a参数和b参数,但是实际上不是,在java编译器编译以后实际的操作代码是:
class Outer$Dosome{
public Dosome(final String a,final int b){
this.Dosome$a=a;
this.Dosome$b=b;
}
public void dosome(){
System.out.println(this.Dosome$a+this.Dosome$b);
}
}}
从以上代码看来,内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。
这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。
作者: 克零岚    时间: 2013-3-5 16:49
呵呵,复习了一小下,请看:

(1)所谓“局部内部类”就是在对象的方法成员内部定义的类。而方法中的类,访问同一个方法中的局部变量,却必须要加上一个final。
(2)原因是编译程序实现上的困难:内部类对象的生命周期会超过局部变量的生命期。
局部变量的生命期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,退栈,这些局部变量全部死亡。
内部类对象生命期,与其它类一样,当创建一个局部内部类对象后,只有当没有其它人再引用它时,它才能死亡。
所以完全可能一个方法已调用结束(局部变量已死亡),但该局部类的对象仍然活着。即:局部类的对象生命期会超过局部变量
(3)局部内部类的对象访问同一个方法中的局部变量,那么这就要求只要局部内部类对象还活着,那么栈中的那些它要访问的局部变量就不能“死亡”(否则:它都死了,还访问个什么呢?)。这就是说:局部变量的生命期至少等于或大于局部内部类对象的生命期
(4)解决方法:局部内部类的对象可以访问同一个方法中被定义为final的局部变量。
定义为final后,编译程序的实现方法:将所有的局部内部类对象要访问的final型局部变量,都拷贝成为该内部类对象中的一个数据成员。这样,即使栈中局部变量(含final)已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,照样可以访问final型局部变量
清楚了没呀?
作者: 夏晓彤    时间: 2013-3-5 16:51
请看此贴http://bbs.itheima.com/forum.php ... mp;page=1#pid239094
作者: 赵家阳    时间: 2013-3-5 17:56
克零岚 发表于 2013-3-5 16:49
呵呵,复习了一小下,请看:

(1)所谓“局部内部类”就是在对象的方法成员内部定义的类。而方法中的类,访 ...

差不多了。
作者: 克零岚    时间: 2013-3-5 18:00
赵家阳 发表于 2013-3-5 17:56
差不多了。

295709646   黑马18届活动交流群
作者: 李阳    时间: 2013-3-5 21:03
李洪因 发表于 2013-3-5 16:24
首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并不与外部类在同一class文件中。
...

受教了,原来真像在这里。
作者: scott0610    时间: 2013-3-6 09:42
Java要求所有被内部类访问的局部变量都使用final修饰也是有其原因的:对于普通的局部变量而言,它的作用域就是停留在该方法内,当方法执行结束,该局部变量也随之消失;但在内部类则可能产生隐式的“闭包”,闭包将使得局部变量脱离它所在的方法继续存在。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2