기본 정보 : MyCustomObject를 생성하는 MyCustomObjectGenerator가 있습니다. 이 객체는 항상 동일한 값으로 생성됩니다. 이 객체에는 mutch 코드, 인터페이스, 열거 형, 하위 클래스가 포함되어 있으므로 여기서 간단하게 설명합니다. 인터페이스의 모든 객체 또는 구현은 같음 & hashCode 메서드를 재정의합니다. 올바른 방식으로 이루어지기를 바랍니다.Java hashCode()는 동일한 객체 생성의 서로 다른 실행에서 다릅니다
이 MyCustomObject는 사용자 지정 serializer가있는 Jackson과 JSON에 직렬화됩니다 (MyCustomObject에는 Jackson 주석과 같은 모든 Jackson 종속성이 없습니다!).
각 JSON은 MyCustomObject의 hashCode (아래 코드 참조)를 기반으로 계산 된 ID를 가져옵니다. 이 ID는 동일한 jsons를 매우 빨리 식별하기 위해 체크섬으로 사용됩니다. UUID를 기반으로하는 다른 ID가 있는데, 이는 작업 자체를 식별하므로 2 개의 작업이 동일한 체크섬을 가질 수 있다는 것을 알고 있습니다!
문제 : JSON을 생성하고 파일에서 미리 정의 된 JSON으로이 JSON을 확인 두 가지의 JUnit - 테스트 (한이 JUnit의 TestClass에 최소한의 & 최대 방법)이있다 . 두 테스트/메소드를 모두 실행하면 JSON은 파일의 JSON과 일치하지만, testMaximal() 메소드 만 실행하면 생성 된 ID가 동일하지 않기 때문에 어설 션이 실패합니다. 따라서 hashCode는 다른 것처럼 보입니다. 두 가지 테스트 메소드를 다시 시작하면 jsons은 파일에서 나온 것과 다시 일치하므로 생성 된 객체에는 ZonedDateTime.now()과 같은 임의의 내용이 들어 있지 않습니다. 다른 JSON 값은 항상 동일하며 ID 만 다릅니다. HashCode는 실행 (2 개의 메소드/1 개의 메소드) 조건이 동일하면 동일하게 보이지만,이 실행 조건이 바뀌면 달라집니다. 이것은 나에게 정말로 이상합니다.
이제 어떤 클래스가 hashCode 메서드를 올바르게 재정의하거나 다른 hashCode를 생성하지 않는지 평가해야합니다. id는 포함 된 모든 객체의 hashCodes를 기반으로합니다. 누군가가 Reflection을 통해 MyCustomObject의 각 객체, 변수, 하위 클래스, 인터페이스의 hashCode를 인쇄하는 좋은 아이디어가 있습니까? 이미 시도 했음
ReflectionToStringBuilder.toString(myCustomObject, ToStringStyle.DEFAULT_STYLE)
그러나 이것은 myCustomObject의 각 하위 하위 요소의 hashCode를 인쇄하지 않습니다.
정확한 개체 값을 포함하여 인쇄 할 수 있다면. hashValue, 그럼 나는 그것을 비교할 수 있습니다.
ReflectionToStringBuilder.toString()과 다른 하나의 개체가 이미 발견되었지만이 개체에는 mutch 인터페이스, 변수 등이 포함되어 있지만이 BlablaObject @ 4fb64261 [...]의 모든 값은 동일하며 거기에 해시 코드는 최고 질문에
누락되었습니다 가 거기에 알려진 경우, 또는 STH "당신이의 HashMap에 키로서 열거를 사용하는 경우, 해시 코드는 자바 스택 또는 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.자바
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