hashcode에 대해서

조회수 1883회

독학과 인강으로 공부하고 있는 초보입니다.

hashcode를 처음 공부하다보니 헷깔리는 부분이 있는데 마땅히 질문할 곳이 없어 이렇게 글을 남기게 되었습니다. 제가 궁금한 소스는 아래와 같습니다. (대충넘어가기보다는 한 줄 한 줄 주석을 달며 이해하고 넘어가는 게 많아 주석이 많습니다. 양해부탁드리고, 혹시나 틀린 내용을 발견하시어 충고해주시면 감사하겠습니다.)

package ObjectExs;

public class EqualsEx1 {

    public static void main(String[] args) {
        int aa = 100;
        int bb = 100;

        String str1 = new String("하이 자바"); // String str1 = "하이 자바" 같다.
        String str2 = "하이 자바";

        System.out.println(str1.hashCode()); // 출력값: 422206472
        System.out.println(str2.hashCode()); // 출력값: 422206472


        if (aa==bb){// 출력값 : aa와 bb는 서로 같다
            System.out.println("aa와 bb는 서로 같다");
        }else {
            System.out.println("aa와 bb는 서로 다르다");
        }
        System.out.println("/////////////str1 = str2;/////////////");
        if (str1==str2){//출력값 : str1와 str2는 서로 다르다
            System.out.println("str1과 str2는 서로 같다");
        }else {
            System.out.println("str1와 str2는 서로 다르다");
        }


        // == 비교연산자는 기본자료형을 비교하는 경우에는 값을 비교한다.
        // 참조형(Reference Type)의 비교는 주소값을 비교한다.
        // equals (반환값 :  true or false)


        System.out.println("/////////////str1.equals(str2)/////////////");
        //오버라이딩함.
        if (str1.equals(str2)){//출력값 : str1와 str2는 서로 같다
            System.out.println("str1과 str2는 서로 같다");
        }else {
            System.out.println("str1와 str2는 서로 다르다");
        }

        Value va1 = new Value(10);
        Value va2 = new Value(10);

        System.out.println(va1.hashCode()); // 출력값: 366712642
        System.out.println(va2.hashCode()); // 출력값: 1829164700 둘의 주소값이 다름
        //hashCode()는 object상속받음, 원칙적으로 주소값이 다른게 원칙

        //va1 = va2;
        //오버라이딩 안함.
        if (va1.equals(va2)){//출력값 : va1와 va2는 서로 다르다 
            //-> but 66~72줄 equals 오버라이딩으로 인하여 같아진다. 
            System.out.println("va1과 va2는 서로 같다");
        }else {
            System.out.println("va1와 va2는 서로 다르다");
        }
        // 오버라이딩 유무에 따라 비교하는 것이 다르다.
        // ->Equals 메소드가 Object 클래스에 있는 경우는 주소값을 비교한다
        // ->String객체의 Equals메소드는 오버라이딩 된 메소드여서 내용을 비교한다.

    }
} //end of EqualsEx1
class Value{
    int a;
        //오버라이딩//오버라이딩을 하여야 내용비교가능
        public boolean equals(Object obj){ //오버라이딩
        if(obj !=null && obj instanceof Value){ // obj가 Value타입인지 확인하는 것
            return a == ((Value)obj).a;
        } else {
            return false;
        }
    }
    public Value(int a){
        this.a = a;
    }
} // end of Value

Q.1 str1과 str2 str1.equals(str2)은 출력값이 str1와 str2는 서로 같다라고 나오는 반면 va1.equals(va2)은 출력값이 va1와 va2는 서로 다르다(오버라이딩안했을 시)라고 나옵니다. 왜 다른지 모르겠습니다. 강좌에서 string은 오버라이딩했다고 하는데 이 소스만 봤을 때는 오버라이딩을 했는지 잘 모르겠습니다.

Q.2 소스 맨 아래 쪽인 boolean을 반환타입으로 갖는 equals메소드의 오버라이딩에 대해 질문이 있습니다. 여기서 매개변수가 object obj인지를 모르겠습니다. 왜 object인지요? 그리고 if문의 조건으로 obj !=null && obj instanceof Value을 사용했는지 모르겠습니다.

강좌를 보고 여기에 질문을 드려 죄송하게 생각하고 있습니다. 거기엔 질문할 수 있는 곳이 없고 구글,네이버에 검색해봐도 제 수준에서는 도저히 이해하기 어려운 부분이라 질문드렸습니다.

1 답변

  • Q.1 답변 자바의 동치 연산인 == 과 equals 에 대한 질문인데,

    == 연산은 원시타입(primitive type, int, char.. 과 같이 소문자로 쓰는 타입들)은 값 자체를 비교합니다. 그러나 그 외의 참조타입(자바에서 원시타입을 제외하고는 모두 객체로 참조타입입니다.)은 메모리 주소를 비교하게 됩니다.

    equals 함수는 자바의 객체모델에서 모든 객체의 최상위 객체인 Object에서 정의하고 있는 함수로써, 다른 객체와의 동치인지 판별하는 연산을 의미하는 함수입니다. 애석하게도 이 함수는 상속한 객체(자바의 모든 객체는 기본적으로 Object를 상속합니다.)에서 직접 구현해주어야 합니다.

    따라서 aa==bb 는 int 타입에 대한 비교임으로 같은것이 맞습니다.

    두번째 str1==str2 는 str1에서 new String(...)을 하여 새로운 주소를 부여하였고, str2에서는 문자열 상수를 대입하였으므로, 같은 주소를 가지고 있지 않습니다. 따라서 다른 것이 맞습니다.

    세번째 str1.equals(str2)는 자바의 기본 String 구현(이 부분은 Java 라이브러리의 원시 소스를 참고하셔야 합니다. OpenJDK 등을 통해서 참고할 수 있습니다.)에서 equals가 오버라이드되어 구현되어 있습니다. 의미적으로 같은 문자열을 가지고 있으므로, 같아야만 합니다. (equals가 잘 구현되어 있으니, 실제로도 같습니다.)

    Q.2 답변 앞에서도 언급한 것 처럼, equals 함수는 최상위 객체인 Object의 함수입니다. Object와 다른 Object와 같은지 비교하는 함수로 제공되는 함수임으로 인자는 Object가 되는 것으로 이해하시면 됩니다. 자바의 모든 객체(클래스)는 결국 Object를 상속하게 되어 있기 때문에, 임의의 모든 객체와 비교할 수 있으려면, 모든 객체의 수퍼타입인 Object를 인자로 할 수 밖에 없습니다.

    그리고 obj !=null && obj instanceof Value의 경우는 obj 가 null 일 경우 this에 해당하는 객체와 비교할 필요도 없이 다릅니다. 따라서 먼저 체크한 것이라고 생각하시면 됩니다. 두 번째 instanceof 경우 obj가 Value 타입인지 검사하는 항목으로, obj가 타입이 다르게 되면, 당연히 같지 않다고 볼 수 있을 겁니다. 그래서 두 가지를 검사하여 둘다 통과할 경우에만, 내부 변수들의 같음을 비교하려는 것입니다.

    • 정말로 감사합니다. 많은 도움이 되었습니다. 이해하기에 무언가 부족했던 부분이 개발자님의 답변으로 이해가 되었습니다. 정말로 감사합니다. 감기걸리기 쉬운 날씨인데 감기조심하시고, 좋은 하루되세요~ 알 수 없는 사용자 2016.4.18 17:52

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)