当我使用 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(...)返回两个不同的值,以及为什么“==”运算符失败?我的印象是这个方法是专门为了识别对同一逻辑对象的引用而实现的?
它们是两个独立的对象(即使它们在概念上可能包含相同的数据),正如
==
为 false 的事实所证明的那样。
System.identityHashCode()
为给定对象返回与默认方法 hashCode() 返回的哈希码相同的哈希码,无论给定对象的类是否覆盖 hashCode()。空引用的哈希码为零。
换句话说,标准
hashCode
仅使用对象的地址。每个不同的对象都会给出不同的值。这与休眠无关,这就是 System.identityHashCode()
的设计原理。
如果您想要您期望的行为,请对 hibernate 返回给您的对象使用
equals
和 hashCode
方法。
您很可能正在使用某种树结构:
this->A<-that
无论是通过
A
还是 this
对 that
进行更改都可以通过任一引用可见,但它们仍然是两个不同的 java 对象,即使它们包装相同的内部值。这很可能是用于支持延迟加载值之类的 Hibernate 代理对象。
要亲自确认这一点,请在调试器中逐步执行并查看实际对象。
我面临同样的问题,但在 JSF 1.2 中,它以某种方式复制 requestScope bean 对象,并且当通过 ajax 请求设置 bean 属性中的值时,该值已设置,但在下一个请求中,先前的值会重新出现为如果它从未被改变过。而且它再也不会经过构造函数,它实际上是直接在机器内存中的复制。在近 10 年的开发中我从未见过这样的事情。