2017-01-31 15 views
0

기본 정보 : 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(); 
    } 
} 
+1

Enum의 기본 hashCode()는 super.hashCode() (java.lang.Object의 구현)로 정의되어 있으므로 각 JVM 인스턴스마다 다릅니다. HashCode 계약에는 "이 정수는 한 응용 프로그램 실행에서 다른 응용 프로그램 실행과 일관성을 유지할 필요가 없습니다." 그래서 당신이 가지고있는 것 같아요 : 열거 형의 경우에도 모든 hashCode() 메서드를 오버라이드하거나 JVM 인스턴스 전체의 안정성을 보장하거나 해시가 각 인스턴스마다 다를 수 있습니다. – GPI

답변

2

hashCode()에 의해 반환되는 값은 실행되는 응용 프로그램마다 다양합니다. 여기에는 다음이 포함

  • 모든 배열 유형
  • 모든 enum 유형의 객체 평등과 개체 ID가 같은 일이다
  • 많은 다른 유형; 예 : Object, 클래스 , 스레드 , StringBuilder / StringBuffer`. 일반적으로

, 자바 SE에 의해 정의 클래스가 Object.equals(Object)에서 의미에과 다른 equals 방법이있는 것으로을 문서화 하지 않은 경우, 당신은 또한 Object.hashCode()를 사용하는 가정 ... 그한다 해시 코드는 실행마다 다릅니다.

1

님의 해시 기반 데이터 구조에서 선택 버킷을 제외하고 hashCode()를 사용 안하고 있습니다. 당신이 알아 낸 바와 같이, 검증 과정에서 확실한 자리는 없습니다.