Java 객체의 해시 코드가 다른 호스트에서 일치하지 않는 이유

2405 단어 javahashcode

배경



최근에 API 고객 중 한 명이 APIetag가 제대로 작동하지 않는다고 불평합니다. 그래서 무엇이 잘못되었는지 확인하기 시작했습니다. 그리고 내가 찾은 것은 다른 호스트의 etag가 일관되지 않다는 것입니다. 따라서 etag는 Java 객체 해시 코드의 16진 문자열입니다. 처음에는 무엇이 잘못되었는지 전혀 몰랐습니다. 다른 API가 작동하기 때문에 API 중 하나만 작동하지 않습니다. 그래서 개체의 각 필드를 인쇄하는 간단한 테스트 코드를 작성했습니다. 마지막으로 Java enum의 해시 코드가 호스트마다 다르다는 것을 알았습니다. 왜?

왜요?



방금 질문을 봤고 이것을 찾았습니다 post. 그것은 내가 가진 것과 정확히 같은 문제입니다.

공식 문서에서 자바 enum 해시코드 정의를 살펴보자.

public final int hashCode()
Returns a hash code for this enum constant.
Overrides:
hashCode in class Object
Returns:
a hash code for this enum constant.


문제가 무엇입니까? 여기에서는 이 열거형 상수에 대한 해시 코드를 반환한다고 말합니다. 열거형 상수는 열거형의 객체이며 상수입니다. 따라서 JVM에서 일관성이 있습니다. 그러나 각 JVM에는 고유한 열거형 상수가 있어야 합니다. 그것은 처음에 내 질문을 설명합니다. 다른 JVM에 있는 열거형은 다른 해시 코드를 갖습니다.

문제를 해결하는 방법?



그래서, 우리는 무슨 일이 일어나고 있는지 알고 있습니다. 그러나 그것을 해결하는 방법. 보시다시피 enum hashcode 함수는 final 메서드입니다. 따라서 이를 재정의할 수 없습니다.

이것은 해시코드를 재정의하는 유일한 방법은 열거형 객체를 사용하는 곳이라는 것을 알려줍니다. 예를 들어 보겠습니다.

class TestDAO {
  private String test1;
  private Type type;

  enum Type {
    APPLE,
    ORANGE
  }
}


TestDAO에서 해시코드 메서드를 재정의해 보겠습니다.

class TestDAO {
  private String id;
  private Type type;

  @Override
  public hashCode(){
    Objects.hashCode(id, type.name());
  }

  @Override
  public equals(){
    ...
  }

  enum Type {
    APPLE,
    ORANGE
  }
}



차이점은 유형 자체 대신 type.name()를 사용한다는 것입니다. 그러면 문제가 해결됩니다. 완벽하지는 않지만 작동합니다.

참조:
https://madhead.me/posts/enums-fuckup/
https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#hashCode()
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag

좋은 웹페이지 즐겨찾기