有两次获得完全相同的对象引用的可能性有多大

时间:2013-04-16 12:40:30

标签: java

我有时会假设如果oldObject != newObject那么对象已经改变了 - 在大多数情况下这似乎是一个公平的假设,但这是否真的是一个错误的假设?

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

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中)。但它有多大可能?我们是否在实际发生之前谈论了几十年的运行时间?

我的道歉 - 请假设oldOweak某种形式的Weak引用,并不能阻止它被收集。也许它是{{1}},因为代码(现在)建议或者引用存储在数据库或某个文件中。

8 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:4)

(我正在回答我认为你真正想知道的事情,而不是你所拥有的特定片段)

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

Java的实现可以选择使用递增的整数进行对象引用,在这种情况下,当引用计数器溢出回0时,只能获得相同的对象引用。其他实现可能使用内存位置,这使得它更有可能相同的参考资料可以重复使用。在任何情况下,如果重要,您应该定义自己的对象标识。

答案 2 :(得分:3)

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

答案 3 :(得分:1)

o == oldO表示ooldO的内存地址相同。所以,除非在某个时候你做o = oldOoldO = o,否则这种情况不可能发生。通过传递性,当然,做foo = o; oldO = foo或任何等价物会达到相同的效果。

答案 4 :(得分:1)

首先,内存地址无关紧要。 Java不是C.对象标识是一种JVM实现 - 它可能依赖或者不依赖于内存地址,但更可能不依赖于内存地址,因为JVM可以自由地在内存中移动对象但必须保持其身份。 / p>

但无论如何。因为你持有对原始对象的引用,所以第二个不能是“相同”的对象。

答案 5 :(得分:0)

永远不会发生。

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

只要引用oldO,您的第二个对象将系统地在另一个memery位置被引用。

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

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

答案 6 :(得分:0)

通过引用旧对象,可以防止它被垃圾收集,因此可以防止新对象可以使用这些内存,因此它们永远不会相等。

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

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

2)这是人为地试图强迫这种情况,因此并没有真正证明什么: - )

答案 7 :(得分:0)

According to the documentation,当对象被垃圾收集时,将清除弱引用。它没有指定“清除”意味着什么,但可能是设置为null。如果它实际上设置为null,则永远不会将null = =声明为任何对象引用,无论其内存位置如何。