【发布时间】:2016-08-25 22:32:08
【问题描述】:
org.hibernate.internal.SessionImpl 继承层次结构中的具体祖先类以这样的方式覆盖 Object.equals(Object),使得行“/* 3 */" 下面返回 false?
package deduper;
import org.hibernate.*;
public class SessionEqualsPuzzler {
public static void main( String... fubar ){
Session aSession /* = ... Get a valid session instance from SessionFactory... */; /* 1 */
assert ( aSession == aSession ) : "This error message WILL NEVER be shown..."; /* 2 */
boolean isEqual = aSession.equals( aSession ); /* 3 */
assert ( isEqual ) : "This error message SHOULD never be shown — but it is anyway for some unknown reason...: " + isEqual; /* 4 */
}
}
如果您使用“-ea” - 启用断言 - 开关运行上述操作,则会抛出一个 AssertionError标记为“/* 4 */”的行。
我已经搜索了所有我能想到的地方。但据我所知,SessionImpl 似乎没有 - 它的任何祖先 - 覆盖 Object.equals(Object).
令人费解的是,“/* 2 */”行的计算结果为真,但“/* 3 */”行却没有!
据我了解,“shallow”身份检查 ("==") 正是默认的 Object.equals(Object) 所做的。对吧?
我的工作假设是 SessionImpl 不会覆盖其继承层次结构中的任何位置的默认 Object.equals(Object)。
还有其他人知道为什么上面的 SessionImpl.equals(Object) 调用评估为假吗?
顺便说一句,我正在使用 Hibernate 4.3.11.Final,因为它物有所值。
更新:Hibernate have acknowledged the existence of the bug, resolved it super quickly——再次感谢@SteveEbersole——and the fix is scheduled to be released in version 5.2.3。
【问题讨论】:
-
执行
System.out.println(aSession.getClass())时会打印什么? -
“据我了解,“浅层”身份检查 ("==") 正是默认 Object.equals(Object) 所做的。对吧?否 - 除了原语,“==”运算符只会验证对象是否是完全相同的对象。如果你想要 .equals 那么你需要调用 .equals。
-
@JBNizet -
System.out.println(aSession.getClass())printsclass com.sun.proxy.$Proxy14顺便说一句,我正在使用 Hibernate 4.3.11.Final,因为它物有所值。 -
好的。所以它不是 SessionImpl 的一个实例。它是一个动态代理,这个代理的调用处理程序决定如何实现equals()。显然,它决定总是返回 false。
-
还有@deduper,因为这是“我的工作,不是你的”......哇。从你的观点来看,有太多事情是错误的,甚至无法开始进入。拥抱开源精神的方式。