Vin*_*Pii 5 java reference inner-classes
题
当实例化一个内部类(NB:非静态)时,它将获得对外部类的引用(基于其构造)。在这种情况下(如果有的话),该参考的持久性有哪些保证?
详细的解释(试图使问题更有意义)
考虑以下简单代码:
public class OuterInnerExample {
private int mInt;
public void startJob() {
InnerRunnable r = new InnerRunnable();
Thread t = new Thread(r);
t.start();
}
private class InnerRunnable implements Runnable {
public void run() {
int localInt = mInt;
System.out.println(localInt);
}
}
}
Run Code Online (Sandbox Code Playgroud)
编译后,如果我们反编译类文件(我曾使用过jad
),则可以观察到它InnerRunnable
具有一个this$0
成员,该成员是对OuterInnerExample
对象的引用。
InnerRunnable
在调用之前,在的编译器综合构造函数中设置此引用super()
(因此避免了this$0
可能null
在对象构造完成之前使用对象(即通过基类)的情况)。
当InnerRunnable
要访问时mInt
,它将使用由编译器合成的静态getter,该静态getter将对的引用OuterInnerExample
作为参数(这将是this$0
)。这个吸气剂就是access$100
方法。
作为参考,可以在以下位置找到反编译的Java:http : //pastebin.com/gr8GB03t。
现在,整个问题是我观察到了(无法解释),类似于以下内容的堆栈跟踪:
FATAL EXCEPTION: main
java.lang.NullPointerException
at <package.name>.OuterInnerExample.access$100(<line where "class OuterInnerExample" is>
at <package.name>.OuterInnerExample$InnerRunnable.run(<line where "public void run()" is>)
Run Code Online (Sandbox Code Playgroud)
这使我认为那this$0
一定是null
在这一点上。
回答您的问题:正如JLS 8.1.3所述:
当内部类(其声明不在静态上下文中出现)引用作为词法封闭类的成员的实例变量时,将使用相应词法封闭实例的变量。
阅读JLS 17.4.5关于发生之前关系:
任何对象的默认初始化发生在程序的任何其他操作(默认写入除外)之前。
这里的默认初始化是指为字段分配默认值。
由于该领域private int mInt
很原始,因此不可能如此null
,因此您必须寻找其他地方。
我的猜测是您正在使用一些自定义编译器,因为这部分:
private OuterInnerExample$InnerRunnable(OuterInnerExample outerinnerexample)
{
this$0 = outerinnerexample;
super();
}
Run Code Online (Sandbox Code Playgroud)
导致编译时错误。您必须super()
在构造函数的第一行调用。
我实际上复制粘贴了您的原始代码并使用 java 1.7 来执行它并且它工作没有问题,所以我们在这里缺少上下文。