일반적으로 equals 메서드만 재 정의하고 hashCode를 재정의 하지 않아,
Object.hashCode의 일반 규약을 어기게 되므로, HashMap, HashSet, Hashtable 같은 해시 기반 컬렉션과 함께 사용하면 오동작하게 된다.
실제 프로젝트에서
Equals와 hashCode를 재정의 하지 않아서 문제가 된 적이 있다.
http://blog.naver.com/rokking1/220920301116
※ hashCode 선언의 규약
- 응용프로그램 실행 중에 같은 객체의 hashCode를 여러 번 호출하는 경우, equals가 사용하는 정보들이 변경되지 않았다면, 언제나 동일한 정수가 반환 되어야 한다.
- equals(object) 메서드가 같다고 판단한 두 객체의 hashCode 값은 같아야 한다.
- equals(object) 메서드가 다르다고 판정한 두 객체의 hashCode 값은 꼭 다를 필요는 없지만, 서로 다른 객체의 hashCode가 다르면 안된다는 규칙에 위반된다.
※ hashCode 재 정의를 하지 않았을 때 발생하는 코드 사항
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | package effectivejava9; public class Test { private int a; private int b; private String c; public Test(int a, int b, String c) { this.a = a; this.b = b; this.c = c; } public int getA() { return a; } public void setA(int a) { this.a = a; } public int getB() { return b; } public void setB(int b) { this.b = b; } public String getC() { return c; } public void setC(String c) { this.c = c; } @Override public boolean equals(Object o) { if ( !(o instanceof Test) ) { return false; } Test compareObject = (Test) o; return compareObject.getA() == a && compareObject.getB() == b && compareObject.getC().equals(c); } } package effectivejava9; import java.util.HashMap; import java.util.Map; public class Main { public static void main(String argsp[]) { Map<Test, String> data = new HashMap<>(); data.put(new Test(1, 2, "3"), "test"); System.out.println(data.get(new Test(1, 2, "3"))); } } | cs |
Test 객체를 만들고 객체를 만들고 equals를 재정의 한 다음,
Map에 넣고 집어넣고 다시 가져오려고 시도하였을 때,
map에 데이터를 넣은 경우와 가져오는 경우에 객체가 서로 달랐기 때문에 hashCode가 서로 달라서 정상적으로 가져오지 못했다.
이 경우는 처음 위에서 언급했던 프로젝트 내에서 발생했던 동일한 오류이다.
map에서 get과 put 동작을 진행할 때, 항상 해시 버킷을 뒤지게 된다. 그러나 서로 다른 hashCode 때문에 찾을 수가 없는 문제가 발생하는 것이다.
※ hashCode 만드는 방법 참고
'JAVA > Effective Java' 카테고리의 다른 글
모든 객체의 공통 메서드 - 규칙 11 clone을 재정의할 때는 신중하라 (0) | 2018.05.29 |
---|---|
모든 객체의 공통 메서드 - 규칙 10 toString은 항상 재정의하라 (0) | 2018.05.29 |
모든 객체의 공통 메서드 - 규칙 8 equeals 재정의할 때는 일반 규악을 따르라 (0) | 2018.05.29 |
객체의 생성과 삭제 - 규칙 7 종료자 사용을 피하라 (0) | 2018.05.29 |
객체의 생성과 삭제 - 규칙 6 유효기간이 지난 객체 참조는 페기하라. (0) | 2018.05.29 |