Java 相同的两个对象的实现等于 class returns 在检查 getClass() 时为 false
Java equals implementation for two objects of the same class returns false when checking getClass()
我已经使用 NetBeans 的默认值为一个对象实现了 hashCode()
和 equals()
:
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + this.unitSystemID;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
LOGGER.debug(getClass().toString());
LOGGER.debug(this.getClass().getClassLoader().toString());
LOGGER.debug(obj.getClass().toString());
LOGGER.debug(obj.getClass().getClassLoader().toString());
if (getClass() != obj.getClass()) {
return false;
}
final UnitSystem other = (UnitSystem) obj;
if (this.unitSystemID != other.unitSystemID) {
return false;
}
return true;
}
在日志记录检查点,我得到:
units.UnitSystem - class
com.utilities.domain.units.UnitSystem
units.UnitSystem -
org.springframework.boot.devtools.restart.classloader.RestartClassLoader@42d353e2
units.UnitSystem - class
com.utilities.domain.units.UnitSystem_$$_jvst6b1_19ed
units.UnitSystem -
org.springframework.boot.devtools.restart.classloader.RestartClassLoader@42d353e2
此时相等性失败并且 equals
returns 错误。
额外的_$$_jvst6b1_19ed
是什么?它来自哪里?
据我了解,如果 classes 来自同一个 class 加载器,它们应该是相等的,它们就是。我在其他任何使用它的地方都没有遇到过这个实现的问题。为什么 getClass()
返回不同的东西?
正如@Andreas 在评论中所说,它通常发生在通过延迟加载获取对象时。要获得初始对象,您应该先取消代理它。这是 Hibernate
的解包器示例
@SuppressWarnings("unchecked")
public static <T> T initializeAndUnproxy(T entity) {
if (entity == null) {
throw new InternalServerException("Entity passed for initialization is null");
}
T unproxy = entity;
Hibernate.initialize(entity);
if (isProxy(entity)) {
unproxy = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
}
return unproxy;
}
public static <T> boolean isProxy(T entity) {
return entity instanceof HibernateProxy;
}
除非您实际上自己子class UnitSystem
,否则不需要精确的class匹配,所以替换
if (getClass() != obj.getClass()) {
return false;
}
和
if (! (obj instanceof UnitSystem)) {
return false;
}
你不能UnitSystem
class final
因为你希望Hibernate能够创建一个子class代理,所以你没有绝对保证 UnitSystem
不会被非 Hibernate 代码子class,但真的需要这样的绝对保证吗?
我已经使用 NetBeans 的默认值为一个对象实现了 hashCode()
和 equals()
:
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + this.unitSystemID;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
LOGGER.debug(getClass().toString());
LOGGER.debug(this.getClass().getClassLoader().toString());
LOGGER.debug(obj.getClass().toString());
LOGGER.debug(obj.getClass().getClassLoader().toString());
if (getClass() != obj.getClass()) {
return false;
}
final UnitSystem other = (UnitSystem) obj;
if (this.unitSystemID != other.unitSystemID) {
return false;
}
return true;
}
在日志记录检查点,我得到:
units.UnitSystem - class com.utilities.domain.units.UnitSystem
units.UnitSystem - org.springframework.boot.devtools.restart.classloader.RestartClassLoader@42d353e2
units.UnitSystem - class com.utilities.domain.units.UnitSystem_$$_jvst6b1_19ed
units.UnitSystem - org.springframework.boot.devtools.restart.classloader.RestartClassLoader@42d353e2
此时相等性失败并且 equals
returns 错误。
额外的_$$_jvst6b1_19ed
是什么?它来自哪里?
据我了解,如果 classes 来自同一个 class 加载器,它们应该是相等的,它们就是。我在其他任何使用它的地方都没有遇到过这个实现的问题。为什么 getClass()
返回不同的东西?
正如@Andreas 在评论中所说,它通常发生在通过延迟加载获取对象时。要获得初始对象,您应该先取消代理它。这是 Hibernate
@SuppressWarnings("unchecked")
public static <T> T initializeAndUnproxy(T entity) {
if (entity == null) {
throw new InternalServerException("Entity passed for initialization is null");
}
T unproxy = entity;
Hibernate.initialize(entity);
if (isProxy(entity)) {
unproxy = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
}
return unproxy;
}
public static <T> boolean isProxy(T entity) {
return entity instanceof HibernateProxy;
}
除非您实际上自己子class UnitSystem
,否则不需要精确的class匹配,所以替换
if (getClass() != obj.getClass()) {
return false;
}
和
if (! (obj instanceof UnitSystem)) {
return false;
}
你不能UnitSystem
class final
因为你希望Hibernate能够创建一个子class代理,所以你没有绝对保证 UnitSystem
不会被非 Hibernate 代码子class,但真的需要这样的绝对保证吗?