JAVA/Effective Java

모든 객체의 공통 메서드 - 규칙 9 equals를 재정의할 때는 반드시 hashCode도 재정의하라

반응형

일반적으로 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(12"3"), "test");
        
        System.out.println(data.get(new Test(12"3")));
        
    }
 
}
cs




Test 객체를 만들고 객체를 만들고 equals를 재정의 한 다음,

Map에 넣고 집어넣고 다시 가져오려고 시도하였을 때, 

map에 데이터를 넣은 경우와 가져오는 경우에 객체가 서로 달랐기 때문에 hashCode가 서로 달라서 정상적으로 가져오지 못했다.

이 경우는 처음 위에서 언급했던 프로젝트 내에서 발생했던 동일한 오류이다.

map에서 get과 put 동작을 진행할 때, 항상 해시 버킷을 뒤지게 된다. 그러나 서로 다른 hashCode 때문에 찾을 수가 없는 문제가 발생하는 것이다.


※ hashCode 만드는 방법 참고




출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙9 인용.


반응형