6

我有时会假设如果oldObject != newObject对象发生了变化——在大多数情况下这似乎是一个公平的假设,但它真的是一个糟糕的假设吗?

简而言之,以下代码在什么情况下会打印“Same!”?

static WeakReference<Object> oldO = null;
...

Object o = new Object();
oldO = new WeakReference(o);

// Do some stuff with o - could take hours or even days to complete.
...

// Discard o (or let it go out of scope).
o = null;

// More stuff - could be hours or days later.
...
o = new Object();

// Later still.
if ( o == oldO.get() ) {
  System.out.println("Same!");
}

我意识到这确实是远程可能的,因为对象引用本质上是对象的内存地址(或者可能在某些 JVM 中)。但可能性有多大?我们是在谈论它实际发生之前的几十年运行时间吗?

添加

我很抱歉 - 请假设这oldO是某种形式的weak参考,不会阻止它被收集。也许Weak就像代码(现在)所建议的那样,或者参考存储在数据库或某处的文件中。

4

8 回答 8

4

永远不会是一样的。oldO 将始终引用初始对象,因此它永远不会被丢弃,并且新对象不能具有相同的地址。

更新:似乎答案已更新以指定这oldO是一个弱参考。在这种情况下,当对象消失时,oldO的引用将变为空。这意味着它永远不会匹配 JVM 中的另一个对象。

于 2013-04-16T12:47:04.633 回答
4

(我正在回答我认为您真正想知道的内容,而不是您拥有的特定片段)

它依赖于实现。对象引用的约定是,只要对象还活着,就没有其他对象将 == 与它进行比较。这意味着在对象被垃圾回收之后,VM 可以自由地重用相同的对象引用。

Java 的实现可能会选择使用递增整数作为对象引用,在这种情况下,只有当引用计数器溢出回 0 时才能获得相同的对象引用。其他实现可能会使用内存位置,这使得相同引用的可能性更大被重复使用。无论如何,如果这很重要,您应该定义自己的对象身份。

于 2013-04-16T13:09:55.493 回答
3

他们不可能平等。您仍然拥有对旧对象 ( oldO) 的引用,因此它永远不会被丢弃。

于 2013-04-16T12:46:14.933 回答
1

o == oldO意味着o与 相同的内存地址oldOo = oldO因此,除非在某个时候,您正在执行or ,否则这不会发生oldO = o。当然,通过传递性,做foo = o; oldO = foo或任何等效的事情都会达到相同的结果。

于 2013-04-16T12:46:35.420 回答
1

首先,内存地址无关紧要。Java 不是 C。对象标识是 JVM 实现——它可能依赖或不依赖内存地址,但更可能不依赖,因为 JVM 可以在内存中自由移动对象,但必须保持其标识。

但不管。因为您持有对原始对象的引用,所以第二个不能是“相同”对象。

于 2013-04-16T12:53:35.840 回答
0

它永远不会发生。

您的第一个对象 ( oldO) 存储在特定的内存位置。

只要引用了 oldO,您的第二个对象就会在另一个内存位置被系统地引​​用。

所以oldO == o将比较两个内存地址,这总是不同的。

如果您取消引用 oldO,它将被垃圾收集,您最终将能够在同一地址创建一个新对象。但是您将无法将它与 oldO 进行比较,因为它已被取消引用。

于 2013-04-16T12:47:55.503 回答
0

通过引用您的旧对象,您可以防止它被垃圾收集,因此您可以防止该位内存可用于新对象,因此它们永远不会相等。

我想知道你是否使用了 SoftReference,你可以保留对旧对象的引用,同时允许它被垃圾收集但是:

1)我假设一旦收集到旧对象,SoftReference 设置为 null 并且

2)这是人为地试图强迫这种情况,所以并不能真正证明任何事情:-)

于 2013-04-16T12:54:43.727 回答
0

根据文档,当对象被垃圾回收时,弱引用将被清除。它没有指定“清除”是什么意思,但推测它设置为null。如果它实际上设置为 null,则无论其内存位置如何,都不会将 null 声明为 == 任何对象引用。

于 2013-04-16T13:50:39.723 回答