基本信息: 我有一個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