将外部类实例设置为null,但内部类实例能够访问外部类的字段。怎么样?

时间:2015-02-04 08:20:00

标签: java nested closures inner-classes

考虑以下代码:

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对象。

3 个答案:

答案 0 :(得分:2)

InnerClass在创建外部类时会自己引用它。如果对外部类的引用为null,则不涉及内部类维护的引用。见the java language ref

  

类O的直接内部类C的实例i与O的实例相关联,称为i的直接封闭实例。在创建对象时确定对象的直接封闭实例(如果有)(第15.9.2节)。

答案 1 :(得分:2)

您要更新的只是对实例的引用,而不是实例本身。引用只是指向别的东西。

将其想象为手机中的通讯录 - 您正在存储您的朋友'电话号码,以便您可以拨打他们的电话;从联系人中删除他们的号码并不会使他们的手机消失。

答案 2 :(得分:1)

为每个类添加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仍然有对它的引用,因此它不会被最终确定,因此仍然可以访问。

如果您将ob以及ob1设置为null,则输出将为:

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

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