Java:何时取消引用变量

时间:2019-03-28 19:50:14

标签: java memory dereference

试图获得一些Java遵循的后台内存引用和规则。

这是一段代码。 基本上,此类用于实例化某些其他对象(MyOtherObject),之后将对此对象的引用doClose()方法发送到Vector。

如果创建了3个MyOtherObject对象,则Vector将具有3个条目。

最终将调用一个过程,使侦听器迭代MyOtherObject对象的Vector并为每个对象调用doClose()。

当前代码显示

 myOtherObject = new myOtherObject();

作为活动行。使用此行时,实际上将关闭3个MyOtherObject对象中的1个。

如果代码更改为

   MyOtherObject myOtherObject = new MyOtherObject();

然后3个MyOtherObject对象中的每一个都将调用其doClose()例程。

public class MyObject
{
    MyOtherObject myOtherObject ;

     public static MyObject getInstance()
     {
            :
            :
            :
         return instance;
     }

    public void runThis () 
    {

        ///MyOtherObject myOtherObject = new MyOtherObject(); //Works

        myOtherObject = new myOtherObject();  //Only closes one

        MyCustomObjectTracker customObjectTracker = new MyCustomObjectTracker()
                {
                    @Override
                    public void closingMyWindows()
                    {
                            myOtherObject.doClose();
                    }
                };

        refernceToSomeOtherObject.addMyObjectTracker(customObjectTracker);
    }
}

由于“工作”中的变量是本地变量,以后将不再提供引用,因此Java会在变量超出范围时用实际的对象引用替换该变量吗? >

在仅关闭1的“不工作”方案中,这是因为变量是实例变量,并且在对doClose()对象进行引用时,它使用的引用恰好位于myOtherObject变量中, doClose()的执行时间?

基本上在寻找什么/何时这些对象在幕后被取消引用,以及是否有用于该行为的正式术语。

1 个答案:

答案 0 :(得分:1)

我认为,您的困惑不是关于取消引用。我认为您的困惑是关于关闭。当像完成一样创建一个匿名类实例时,就是在做一个闭包,它做一些魔术调用堆栈,以获取局部变量的当前状态。让我们首先看一下您的工作示例。 (我已删除了此说明不必要的一些内容)

public class MyObject {
    public void runThis() {
        MyOtherObject myOtherObject = new MyOtherObject();
        MyCustomObjectTracker customObjectTracker = new MyCustomObjectTracker() {
            @Override
            public void closingMyWindows() {
                myOtherObject.doClose();
            }
        };
    }
}

当您执行new MyCustomObjectTracker() { ... }时,Java编译器会看到您使用了变量myOtherObject,因此它隐式地封闭了该变量,以备以后使用。请注意,这里重要的是,每次调用runThis时,您都在创建一个 new 局部变量。它的名称可能与旧名称相同,但是您创建了一个新的局部变量。因此,每个customObjectTracker都可以访问不同局部变量。因此,一切顺利。现在,让我们看看您的另一个示例。

public class MyObject {
    MyOtherObject myOtherObject;
    public void runThis() {
        myOtherObject = new MyOtherObject();
        MyCustomObjectTracker customObjectTracker = new MyCustomObjectTracker() {
            @Override
            public void closingMyWindows() {
                myOtherObject.doClose();
            }
        };
    }
}

在这里,代码遵循相同的原理。我们需要关闭称为myOtherObject的东西。但是myOtherObject不是局部变量;这是一个实例变量。因此,实际上,我们需要封闭它所属的对象this。请注意,只有一个this。您可以多次拨打runThis;您只在一个对象上调用它。因此,在这种情况下,您要多次更改一个变量,然后创建几个都指向该变量的新类。

匿名类相对容易被手工分解为“真实”类。因此,如果闭包使您感到困惑,请尝试将每个代码段转换为不使用匿名类的形式(因此,用new MyCustomObjectTracker() { ... }代替新的class MySpecialCustomObjectTracker extends MyCustomObjectTracker)。这样,您就可以考虑必须将什么状态传递给新对象,这是编译器在创建匿名类实例时自动执行的操作。