본문 바로가기

자바/정리

(JAVA) Object 클래스 toSting(), hashcode()

다음으로 toString을 살펴보겠다.

toSting()은 객체를 문자열로 변환을 시켜주는 메서드 이다. 보통 개발자들은 toString을 사용하여 객체가 무슨 값을 가지고 있는지 직접 확인하는 용도로 사용을 한다. 바로 살펴보자.

 

class dog {
    String crying;
    int number;
    dog(String crying, int number) {
        this.crying = crying;
        this.number = number;
    }
    public boolean equals(Object obj){
        dog d = (dog)obj;
        return this.crying == d.crying;
    }
}
class Main {
    public static void main(String[] args) {

        dog poodle = new dog("멍멍!", 2);
        dog maltese = new dog("멍멍!",5);
        dog chiwawa = new dog("으르렁..",6);
        System.out.println(poodle);
        System.out.println(poodle.toString());
        System.out.println(maltese.toString());
        System.out.println(chiwawa.toString());
    }
}

 

 

출력 결과는 다음과 같다.

dog@7a79be86
dog@7a79be86
dog@34ce8af7
dog@b684286

 

 

잘 살펴보니 toSting을 안써도 푸들이 같은 결과를 표현하고 있다.

System.out.println(poodle);
System.out.println(poodle.toString());

사실 자바는 객체를 호출할때 toString을 기본적으로 쓰도록 설정하고 있다. 해서 toSting을 입력 안해도 값을 보여주게 된다. 그런데 잘 살펴보면

dog@7a79be86

이게 뭔지 우리가 어떻게 알겠는가? 어림도 없다.

 

toString 다음에 설명하겠지만 dog는 클래스명 @는 위치 7a79be86는 16진수를 사용한 해쉬코드이다. 어? hashcode() 설명이 끝난건가? 이건 기다려 달라.

 

그런 이유로 우리는 사용의 목적에 맞게 toString 또한 equals 처럼 오버라이딩 하여 사용해야 한다.

class dog {
    String crying;
    int number;
    dog(String crying, int number) {
        this.crying = crying;
        this.number = number;
    }
    public String toString(){
        return "짖기 = " + crying + " 마릿수 = " + number;
    }
}
class Main {
    public static void main(String[] args) {

        dog poodle = new dog("멍멍!", 2);
        dog maltese = new dog("멍멍!",5);
        dog chiwawa = new dog("으르렁..",6);
        System.out.println(poodle);
        System.out.println(poodle.toString());
        System.out.println(maltese.toString());
        System.out.println(chiwawa.toString());
    }
}

출력 결과는 다음과 같다.

짖기 = 멍멍! 마릿수 = 2
짖기 = 멍멍! 마릿수 = 2
짖기 = 멍멍! 마릿수 = 5
짖기 = 으르렁.. 마릿수 = 6

 

 

간단하게 오버라이딩을 해주니 우리가 보기 편안한 양식으로 변경이 되었다. 이렇게 사용들 한다.

 

 

 

마지막으로 hashcode()를 살펴보겠다.

위에서 16진수 hashcode()를 보여주었다. (dog@7a79be86)

 

이게 왜 필요할까? 앞서, 우리는 equals에 대해 학습할때 주소값에 대하여 알게 되었다. 그런데 메모리 주소값은 우리가 봤을때 복잡하게 되어 있을뿐더러 자바에서는 주소값 확인을 제공하지 않는다.(이거 때문에 고생했다..)

 

해서 자바는 주소값을 사용하여 객체 고유의 hashcode를 생성하게 되는데 이는 우리의 가독성을 높혀준다.

 

 

우리가 hashcode()를 사용하는 목적은 같은 값을 가지고 있으면 같은 객체로 판단하도록 하기 위함이다. 예를들어 푸들도 강아지고 말티즈도 강아지면 같은 강아지로 보겠다는 것이다.

사실 hashcode()는 컬렉션에서 중요하게 다루는 개념이라 여기서는 기본 설명만하고 컬렉션 게시글에서 추가로 설명하도록 하겠다.

 

이전에 equals 에서 오버라이딩을 하여 사용하는 방법을 알아보았는데 자바에는 규칙이 있다. 나중에 자세히 다루겠지만 해시충돌을 막기위해 equals로 오버라이딩 하여 true 값을 만들었다면 hash값도 같게 만들어 줘야 한다.

 

해서 equals를 오버라이딩 하면 필수로 hashcode도 오버라이딩 해줘야 한다.

 

 

우선 기본적인 hashcode를 살펴보자.

class dog {
    String crying;
    int number;
    dog(String crying, int number) {
        this.crying = crying;
        this.number = number;
    }
    public boolean equals(Object obj){
        dog d = (dog)obj;
        return this.crying == d.crying && this.number==d.number;
    }
}
class Main {
    public static void main(String[] args) {

        dog poodle = new dog("멍멍!", 2);
        dog maltese = new dog("멍멍!",2);
        System.out.println(poodle); // 16진수
        System.out.println(poodle.equals(maltese)); //T
        System.out.println(poodle.hashCode()); //10진수
        System.out.println(maltese.hashCode());
    }
}

출력결과는 다음과 같다.

dog@7a79be86
true
2054798982
885951223

 

객체는 16진수를 가지고 주소값을 만들게 된다. 해서 toString으로 바로 객체를 불러 버리면 해쉬값이 16진수로 표현이 된다. 그래서 7a79be86 이런 값을 가지게 되는데.

 

hashcode()를 사용하여 호출하게 되면 2054798982 이처럼 자바가 알아서 보기 편한 10진수로 변환해 준다.

 

 

 

앞서 말한 해쉬충돌로 인해 해쉬값을 맞춰 줘야 한다고 했는데 오버라이딩을 하면 된다.

import java.util.Objects;

class dog {
    String crying;
    int number;
    dog(String crying, int number) {
        this.crying = crying;
        this.number = number;
    }
    @Override
    public boolean equals(Object obj){
        dog d = (dog)obj;
        return this.crying == d.crying && this.number==d.number;
    }
    @Override
    public int hashCode() {
        return Objects.hash(crying, number);
    }
}
class Main {
    public static void main(String[] args) {

        dog poodle = new dog("멍멍!", 2);
        dog maltese = new dog("멍멍!",2);
        System.out.println(poodle); // 16진수
        System.out.println(poodle.equals(maltese)); //T
        System.out.println(poodle.hashCode()); //10진수
        System.out.println(maltese.hashCode());
    }
}

출력 결과는 다음과 같다.

dog@576b6962
true
1466657122
1466657122

 

오버라이딩을 해주니 해쉬값이 같아 진것을 확인할수가 있었다.

 

 

참고로 맥 사용자는 모르겠지만... 윈도우 사용자는 Alt insert 키를 눌러주게 되면.

equals 와 hashcode 오버라이딩을 자바가 알아서 만들어 줘서 더욱 쉽게 작성 할수 있다.

 

잊지말자 equals와 hashcode는 같이 움직이는 것을.

 

'자바 > 정리' 카테고리의 다른 글

(JAVA)Collection Framework  (0) 2022.12.18
(JAVA)제네릭  (0) 2022.12.13
(JAVA) Object 클래스 equals()  (0) 2022.12.08
(JAVA) 예외  (1) 2022.11.30
(JAVA)다형성  (0) 2022.11.25