public class Test001_InnerClass {
public static void main(String[] args){
method();
}
private static void method() {
final int x = 0;
// int y = 1;
class inner{
//存在以下的一个拷贝
//final int x = 0;
//不能访问
// y = 2;
public inner() {
System.out.println(x);
//下面不能访问
// System.out.println(y);
}
}
new inner();
}
}
class outer{
void in(){
new inner();
}
class inner{
}
}
作者: 左建飞 时间: 2012-8-14 18:15
实际开发不知道这个原因可能出现错误。
final修饰后,编译器是这样处理内部类的,如果这个外部局部变量是常量,则在内部类代码中直接用这个常量。如果是类的实例,则编译器将产生一个内部类的构造参数,将这个final变量传到内部类里,这样即使外部局部变量无效了,还可以使用。
内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。
这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是 final来规避这种莫名其妙错误的存在 。作者: 方志亮 时间: 2012-8-14 18:20
因为方法中的代码是由上而下顺序执行的,方法运行结束后,局部变量就被销毁,内部类的生命周期可能会比局部变量的生命周期长;看下面的代码,方法中的内部类 Inner.class 调用方法中的局部变量 x ,正常调用的时候内部类能够调用到方法中的局部变量,并将内部类对象 inner 返回,正常调用结束后,如果方法中的局部变量 x 没有被 final 关键字修饰,x 则会被销毁,我们再通过反射的方式去调用 x 的时候则会发现找不到变量 x ,如果局部变量 x 被 final 关键字修饰后,则 x 在方法运行结束后不会被销毁,而是常驻在内存中直到 JVM 退出,这样再通过反射调用的时候依然可以找到 x 。
*/
class Outer {
public Object outerfun() {
final int x = 5;
class Inner {
public void innerfun() {
System.out.println(x);
}
}
Inner inner = new Inner();
inner.innerfun();
return inner;
}
}