equals method and hashCode Method


 이번 Posting에서는 equals method와 hashCode method에 대해서 정리를 할 것이다.

equals

1
2
3
public boolean equals(Object obj) {
    return (this==obj);
}

메소드를 보면 파라미터로 넘어온 객체와 자기자신을 비교연산자를 통해 비교하여 값을 리턴하고 있다.

 그렇다면 여기서 비교하고 있는 것은 "주소 값"일까? 아니면 주소 값이 가리키는 데이터일까?

정답은 주소 값을 비교하는 것이 맞다. 아래의 예제를 보면 확실할 것이다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Testing {
    public static void main(String[] args) {
        Value value1 = new Value(1);
        Value value2 = new Value(1);
        System.out.println((value1.equals(value2)) ? "같다" : "다르다");
> 다르다
        value1 = value2;
        System.out.println((value1.equals(value2)) ? "같다" : "다르다");
> 같다
    }
}

class Value {
    int x;
    Value(int x) {
        this.x = x;
    }
}

String Object

다음의 경우를 보자.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class Testing {
    public static void main(String[] args) {
        String string1 = new String("1");
        String string2 = new String("1");
        System.out.println((string1.equals(string2)) ? "같다" : "다르다");
        string1 = string2;
        System.out.println((string1.equals(string2)) ? "같다" : "다르다");

    }
}

이 경우 출력되는 값은 무엇일까? 위와 같다면 예제를 작성하지도 않았을 것이다.

답은 같다 같다 이다.

String class의 경우 값을 비교하기 위해 Ojbect class로부터 상속 받은 equals method를 override하여 값을 비교할 수 있도록 작성한 것이다. 따라서 같다같다.라는 결과 값이 나온 것이다. 이외에도 Date, File, wrapper 클래스도 override 되어있다. StringBuffer는 의외로 overriding되어 있지 않다.

하지만 보통 String 객체를 만들때 new String을 사용한단 말인가?


1
2
String string1 = "test";
String string2 = new String("test");

 line 1과 line 2의 차이는 무엇일까? 다음 그림을 보자.


 line 1번과 같이 코드를 작성한다면 바로 Constant pool 에 저장 된다. 이 메모리는 단 하나의 참조변수가 참조하고 있다면 사라지지 않는다.
반면, line 2의 경우 객체를 생성한 경우 참조변수가 heap 영역에 메모리 주소를 가리키게 된다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Testing {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        System.out.println(s1 == s2);
        > true
        System.out.println(s1.equals(s2));
        > true
        String s3 = new String("h");
        String s4 = new String("h");

        System.out.println(s3 == s4);
        > false
        System.out.println(s3.equals(s4));
        > true
    }
}

따라서 위와 같은 결과가 도출된다.



hashCode method


hashCode는 hashing 기법에 사용되는 해시 함수를 구현한 것이다. 또한 해시 코드를 반환하는데 Object class에 구현된 hashCode method는 모든 객체가 서로 다른 해시코드 값을 가지도록 구현이 되어있다.
사실 상 해시는 해시충돌이 발생할 수 있다고 지난 Posting에서 소개한바 있다. 따라서 위의 해시 함수도 충돌이 발생하여 서로 다른 객체라고 해도 해시 값이 서로 같을 수 있다.

하지만 프로그램이 새로 시작할 때, 객체가 할당 받는 메모리는 항상 다르기 때문에 다른 두 객체는 서로다른 해시코드 값을 갖게된다.


해시코드를 이용하여 클래스의 멤버 변수 값으로 같다고 판단하게 만들려면 hashCode method를 override해야할 것이다.

String 클래스는 hashCode method가 이미 override 되어있는데 정말로 문자열이 같다면 hash code 값도 일치할 것이다.



toString method 

toString 메소드는 인스턴스에 대한 정보를 문자열로 제공할 목적으로 정의한 것이다.
override를 하지 않는 이상 class name과 hash code 값을 반환할 것이다.



이 블로그의 인기 게시물

웹툰 무료로 볼 수 있는 사이트

BackJoon 1011, Fly me to the alpha centauri, 규칙 찾기 문제

BaekJoon 6591, 이항 쇼다운 조합문제