【发布时间】:2017-10-08 00:38:18
【问题描述】:
当我使用 this 引用在内部调用对象时,Java 方法 System.identityHashCode(...) 为对象返回不同的值,而不是在相同的变量引用上调用它对象。
class MyObject {
public void test(MyObject that){
LOGGER.info("this hash: {}",System.identityHashCode(this));
LOGGER.info("that hash: {}",System.identityHashCode(that));
LOGGER.info("equals: {}",this == that);
}
}
还有测试...
MyObject o = new MyObject();
o.test(o);
还有输出...
this hash: 263009111
that hash: 524075148
equals: false
什么会导致这种情况发生?有问题的真实对象是一个 Hibernate 实体,但我已将上述测试直接添加到代码中,并且它在特定场景中显示出相同的行为。为什么使用 this 关键字的对象会显示与引用自身不同的身份哈希码?我还通过设置对象的一些字段并确认本地字段设置为相同的值来确认引用是正确的。 那么如果引用是正确的,为什么identityHashCode(...)会返回两个不同的值,为什么“==”操作符会失败呢?我的印象是这个方法是专门为识别对同一个逻辑对象的引用而实现的?
【问题讨论】:
-
“为什么一个对象会使用 this 关键字显示不同的身份哈希码,而不是在对自身的引用上显示不同的身份哈希码”MVCE 可能会很好。
-
通过引用是同一个对象。我可以设置对象的字段,例如 this.myField =
,然后测试 that.myField == this.myField,结果为真。不幸的是,我只能在我不拥有的代码上下文中重现它,所以我无法提供 MCVE。现在我的预感是休眠状态正在对破坏身份/此合同的实体做一些事情,但我无法弄清楚那是什么或为什么。 -
也许这个stackoverflow.com/questions/25340606/… 增加了一些洞察力(Hibernate 为实体对象创建代理对象以支持延迟加载)
-
@DanWatson 更改一个对象的字段会影响另一个对象的字段这一事实并不一定证明每个引用都是同一个对象。一个可以简单地是一个围绕另一个的包装类:例如,如果您创建一个
ArrayList a,然后创建一个List b = Collections.synchronizedList(a),对 b 的任何修改也将修改 a。但它们不是同一个对象! -
我认为hibernate的评论更正确。被设置的字段不是一个复杂的对象。它是一个原始字段,在两个地方都设置为完全相同的值,但只能通过一次赋值。我认为正在发生的事情是休眠 javassist 魔术正在弄乱 this 运算符,因此它从变量引用返回不同的身份。