将外部 class 实例设置为空,但内部 class 实例能够访问外部 class 的字段。如何?

Setting outer class instance to null, and yet inner class instances is able to access outer class's field. How?

考虑以下代码:

class OuterClass{
    String ocs="ocs";
    class InnerClass{
        String ics="ics";
        void innerMeth(){
            System.out.println(ocs);
        }
    }
}
//main class
public class HelloWorld{
    public static void main(String []args){
        OuterClass ob=new OuterClass();
        OuterClass.InnerClass ob1=ob.new InnerClass();
        ob=null;
        ob1.innerMeth();
    }
}

仍然打印出字符串 'ocs' .
基本上即使我已将 OuterClass 实例设置为 null。
InnerClass 实例仍然可以访问 OuterClass 引用的字段 ocs
如何 ?

这与闭包有关吗??即,即使上下文不再存在,在本例中为 OuterClass 对象,也会在上下文中维护变量。

InnerClass 在创建时存储自己对外部 class 的引用。如果您将对外部 class 的引用置空,则这与内部 class 维护的引用无关。参见 the java language ref

An instance i of a direct inner class C of a class O is associated with an instance of O, known as the immediately enclosing instance of i. The immediately enclosing instance of an object, if any, is determined when the object is created (§15.9.2).

您正在更新的只是对实例的引用,而不是实例本身。引用只是指向其他东西的东西。

把它想象成您 phone 中的联系人 - 您正在存储朋友的 phone 号码,以便您可以拨打他们的 phone;从您的通讯录中删除他们的电话号码不会使他们的 phone 消失。

在每个 class 中添加 finalize() 方法可以更好地理解。

 class OuterClass {
    protected void finalize() throws Throwable {
        System.out.println("oc instance finalized..");
    };
    String ocs = "ocs";

class InnerClass {
    String ics = "ics";

    protected void finalize() throws Throwable {
        System.out.println("IC instance finalized");
    };

    void innerMeth() {
        System.out.println(ocs);
    }
}

}

// main class
class HelloWorld {
    public static void main(String[] args) {
        OuterClass ob = new OuterClass();
        OuterClass.InnerClass ob1 = ob.new InnerClass();
        ob = null;
        // ob1=null;
        System.gc();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ob1.innerMeth(); // you will get NPE here
    }
}

当只有 ob 设置为 null 时,ob1 仍然有对它的引用,所以它不会被最终确定,因此仍然可以访问。

如果将 obob1 设置为 null,则输出将为:

 IC instance finalized
oc instance finalized..
Exception in thread "main" java.lang.NullPointerException
    at HelloWorld.main

因为没有对 obob1 的引用,因此两个对象都是 finalized。请注意,它是设置为空的 reference。其他引用可能仍然指向该对象以及 ob(在您的情况下 ob1