java - Java:何时取消引用变量
问题描述
希望获得一些 Java 遵循的幕后内存引用和规则。
这是一段代码。基本上,此类用于实例化一些其他对象(MyOtherObject),之后对该对象的 doClose() 方法的引用被发送到 Vector。
如果创建了 3 个 MyOtherObject 对象,则 Vector 将有 3 个条目。
最终将调用一个进程,导致 Listener 遍历 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()?
基本上是在寻找这些对象在幕后被取消引用的内容/时间,以及该行为是否有官方术语。
解决方案
我不认为您的困惑与取消引用无关。我认为你的困惑是关于闭包的。当你像你一样创建一个匿名类实例时,你正在创建一个闭包,它会做一些神奇的调用堆栈来获取局部变量的当前状态。让我们先看看你的工作示例。(我已经删除了一些对这个解释不必要的部分)
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
时,都会创建一个新的局部变量。它可能与旧的名称相同,但您创建了一个新的局部变量。所以每个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
)。这样做会让您考虑必须将什么状态传递给新对象,这是编译器在您创建匿名类实例时自动执行的操作。
推荐阅读
- android - 如何查找 lat.lng 是否在谷歌地图的某个半径范围内
- python - 如何从python中的列表元素中删除转义序列?
- python - 在服务器中运行 Bokeh 应用程序后如何重用终端
- mapbox - 如何在国家/地区掩盖/修剪 voronoi 多边形?
- javascript - Jest 方法调用计数错误?
- three.js - 更新几何值
- javascript - 为什么 Application Insights 在 Firefox 上作为 CORS 被阻止?
- packer - 如何将打包程序运行 AMI 配置脚本的目录从 /tmp 更改为 /opt
- javascript - 即使在建立连接后,Flask socketio 也没有收到来自 javascript 的任何消息
- azure - 使用 new-azwebapp 时如何选择运行时环境?