基本信息: 我有一个MyCustomObjectGenerator,它生成MyCustomObject。该对象(应该)始终使用相同的值创建。这个对象包含mutch代码,接口,枚举,子类......,所以我在这里简单说明。接口的所有对象或实现都会覆盖equals & hashCode方法(希望以正确的方式)。Java hashCode()在创建相同对象的不同执行方面有所不同
这个MyCustomObject被序列化为带有自定义序列化器的Jackson的JSON(MyCustomObject不包含任何杰克逊依赖项,比如Jackson注释!)。
每个JSON都会根据MyCustomObject的hashCode获取一个ID(请参阅下面的代码)。这个ID只是作为校验和来快速识别相同的jsons。还有另一个基于UUID的ID,用于标识作业本身,所以我知道2个作业可以具有相同的校验和!
问题: 有两种基于JUnit测试(在一个Junit的-识别TestClass最小&最大法),即产生JSON,并检查此JSON与来自文件的预定JSON。如果我运行这两个测试/方法,JSON与文件中的JSON匹配,但是如果我只是运行testMaximal()方法,断言失败,因为生成的ID不相同。所以hashCode似乎有所不同。如果我再次启动两个测试方法,jsons再次与文件中的那个匹配,所以生成的对象不包含任何随机内容,如ZonedDateTime.now()。其他JSON值始终相同,只有ID不同。如果执行(2个方法/ 1个方法)条件相同,则HashCode似乎相同,但如果此执行条件发生更改,则HashCode会有所不同。这对我来说真的很奇怪。
现在我必须评估什么类不能正确覆盖(或产生不同的hashCode)hashCode方法(id是基于所有包含对象的hashCodes)。是否有人有任何好主意通过反射来打印MyCustomObject的每个对象,变量,子类,接口的hashCode?我已经试过
ReflectionToStringBuilder.toString(myCustomObject, ToStringStyle.DEFAULT_STYLE)
但是这不会打印myCustomObject的每个子子元素的hashCode。
如果我可以打印确切的对象值incl。 hashValue,然后我可以比较它。
我已经找到一个与ReflectionToStringBuilder.toString()不同的对象,但是这个对象本身包含了mutch接口,变量等等,但是这个BlablaObject @ 4fb64261 [...]中的所有值都是相同的,哈希码缺少
在顶部问题: 是否有已知的情况下,这hashCode()方法的行为古怪,如“如果你在一个HashMap使用枚举为重点,然后的hashCode依赖于Java堆栈或JVM版本”心向往之。像那样。
CODE
MyCustomObjectGenerator的.java
public class MyCustomObjectGenerator {
private MyCustomObject(){};
public static MyCustomObject generate(boolean isMinimal){
//if minimal then create minimal object
//if minimal == false then create maximized object**strong text**
MyCustomObject myCustomObject = new MyCustomObject(...);
myCustomObject.setXY(...)
...
return myCustomObject;
}
}
MyCustomObject。java的
import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
public class MyCustomObject {
//variables, enums, interface ... here
...
public MyCustomObject(...){...}
//mutch code here
...
public String getChecksum() {
String id = Integer.toString(hashCode());
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(id.getBytes("UTF-8"));
id = DatatypeConverter.printHexBinary(digest);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
// do nothing here
}
return new id;
}
@Override
public int hashCode() {
return new HashCodeBuilder(-1013166723, 372138085)
//if needed in extended classes: .appendSuper(super.hashCode())
.append(...)
....
.toHashCode();
}
@Override
public boolean equals(
final Object other) {
if (!(other instanceof MyCustomObject)) {
return false;
}
MyCustomObject castOther = (MyCustomObject) other;
return new EqualsBuilder()
// if needed in extended classes: .appendSuper(super.hashCode())
.append(..., ...)
....
.isEquals();
}
}
Enum默认的hashCode()被定义为super.hashCode()(java.lang.Object的实现),因此每个JVM实例都有一个不同。 HashCode合同规定:“从应用程序的一次执行到同一应用程序的另一次执行,此整数不必保持一致。”所以我想你有它:要么覆盖每个hashCode()方法,即使对于枚举,也要确保其跨JVM实例的稳定性,否则每个实例的散列值都会有所不同。 – GPI