内部类引用局部变量为什么要求必须是final的,而引用全局变量就不需要

例如在类的方法中定义一个类变量,然后开启一个线程,线程体中引用这个变量,要求必须是final的。
 

8个回答

[code="java"]public class LocalInnerClassUnitTests {

public void defineInnerClass(final int x) {
    class MyLocalInnerClass {                        
        public void doSomething() {
            System.out.println(x);
        }
    }
}

}[/code]

int x 是本地变量,因为java底层的机制不能存取本地变量,这样导致内部类,没有办法取过来,所以java用了一个小聪明,直接把本地变量的refrenece拷贝到内部类。

因为这个小聪明,一般容易让人误解。所以他在编译器里面,加上了一个final,让你不要改变这个值,然你只读不能存,这样感觉就好了

因为没有闭包机制,所以只能通过一个确定的ref来传进去

你所说的内部类,应该是匿名内部类吧

比方说
[code="java"]public class LocalInnerClassUnitTests {
public void defineInnerClass(final int x) {
class MyLocalInnerClass {

public void doSomething() {
System.out.println(x);
}
}
}
}[/code]

简单的说,Java PL 与底层 bytecode 都沒有办法获得一个 local variable(local variable 所使用的 storage 本身)的 "reference",导致 nested class object 没有办法"存取" local variable 的值,勉強能做到"取"而已。底层的做法是把 local variable 的 "value" copy 一份给 nested class(对于 primitive type 甚至不需要 copy),來做出 nested class 读取 local variable 的效果。

这样看起來像是限制你對 local variable 的存取能力,其實是天生就沒有辦法在 local variable 所在 method 以外的 method 去"存取" local variable,只是 final 的介入让事情变得合理。

总而言之,就好像设计者犯错了一样,然后想了一个trick弥补一下。。。

以上是我的想法

局部匿名类在源代码编译后也是要生成对应的class文件的(一般会是A$1.class这种形式的文件),那么这个二进制文件是独立于其外围类(A.class)的,就是说它无法知道A类中方法的变量。但是A$1.class又确实要访问A类对应方法的局部变量的值。。。怎么办呢?
于是干脆就要求“匿名内部类调用的方法内局部变量必须为final”,这样A$1.class访问A类方法局部变量部分就直接用常量来表示

另外引用别人的一段话:
内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。
这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在

[quote] 局部匿名类在源代码编译后也是要生成对应的class文件的(一般会是A$1.class这种形式的文件),那么这个二进制文件是独立于其外围类(A.class)的,就是说它无法知道A类中方法的变量。但是A$1.class又确实要访问A类对应方法的局部变量的值。。。怎么办呢? [/quote]

加载了A$1.class必然会加载A.class,你这种说法太牵强了吧。。。

[quote]加载了A$1.class必然会加载A.class,你这种说法太牵强了吧。。。[/quote]
8) 好像没哪句是这个意思

[quote]还有一种理解: 因为局部变量在失去作用域的时候是要被系统回收的,所以就设置成final,但是不清楚final是会让这个变量获得更长的生命周期呢?还是会在使用内部类中留下一份拷贝?[/quote]

别瞎猜了

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问