Java是否保证对外部类的引用的持久性?如何进行以下跟踪?

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在这一点上。

Ada*_*old 1

回答您的问题:正如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 来执行它并且它工作没有问题,所以我们在这里缺少上下文。