Java - hashCode(), toString()

춤추는개발자·2022년 11월 26일
0

Java 정리

목록 보기
28/59

hashCode()

  • 객체의 해시코드(hash code)를 반환하는 메서드, 해시코드 값 : 정수 값
  • Object클래스의 hashCode()는 객체의 주소를 int로 변환해서 반환
  • equals()를 오버라이딩하면, hashCode()도 오버라이딩해야 한다. equals()의 결과가 true인 두 객체의 해시코드는 같아야 하기 때문이다.
  • 객체마다 다른 해시코드의 반환이 필요할때는 System.identityHashCode(Object obj)를 사용한다. 원래 Object의 hashCode()는 객체마다 주소값을 변환하는 것이기 때문에 다른 값을 반환 합니다.

toString(), toString() 오버라이딩

  • toString() : 객체를 문자열로 변환하는 메서드
public String toString() { // Object 클래스의 toString() 메서드 
   return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
  • 위의 Object 클래스의 toString() 메서드를 오버라이딩하여 원하는 문자열로 출력할 수 있게 작성한다.

공부하면서 알게 된 점

사실 문자열 파트를 공부하면서 equals() 메서드를 처음 접하게 되었다. 거기서는 "=="과 equals() 함수를 배우게 되었고 "=="는 값이 같은지를 비교해 주는 게 아니라 같은 객체인지를 비교해 주는 것이고 equals()는 값이 같은지 비교해 주는 함수로 배웠기 때문에 그렇게 알고 있었다. 근데 Object 클래스의 equals() 메서드를 공부하게 되었고 내가 아는 String 클래스의 equals() 는 Object 클래스의 equals() 메서드를 오버라이딩 한 것을 알게 되었다.
String 클래스 말고도 Date, File, wrapper 등의 클래스들의 equlas()는 값을 비교하는 메서드로 오버라이딩 되어 있다고 한다. 하지만 StringBuffer 클래스는 오버라이딩 되어있지 않다고 한다.
hashCode()를 공부하면서 eqauls() 메서드의 인스턴스 변수 값을 비교하는 메서드로 오버라이딩하면 hashCode()도 오버라이딩 해야된다는 말이 이해가 안되었다. 책을 찾아보니 나는 equals() 메서드를 오버라이딩 하면서 오직 값이 같은지 안 같은지만 비교하는 메서드로 오버라이딩 한다고 생각했다. 근데 책을 보니 그것이 아니라 원래 Object 클래스의 eqauls() 메서드는 객체가 같은지를 판단할 때 참조 변수로만 비교한 것을 오버라이딩하여 인스턴스 변수의 값을 비교하게 만든 것인데 값이 같은지만 비교하니까 값이 같은지를 비교하는 메서드로 바뀌었다고 착각한 것 같다. 하지만 결국 오버라이딩을 하든 안 하든 eqauls() 메서드의 목적은 같은 객체인지를 비교하는 메서드라는 것이다. 결론적으로 equals() 메서드를 오버라이딩 하면 두 객체의 인스턴스 변수 값을 비교하므로 true가 반환되어도 객체는 다른 객체일 수 있다. 그래서 이 객체를 같은 해시코드를 가지게 하기 위해서 hashCode() 메서드도 같이 오버라이딩 해야된다는 것이다.

규칙이다. 오버 라이딩한 equals() 가 true라면 hashCode()도 오버라이딩 해줘야한다.

equals(), hashCode(), toString() 코드

위의 말이 참 길었다. 코드로 결과를 보면 더 쉽게 이해할 수 있다.

import java.util.Objects;

class Card{

    String kind;
    int num;

    Card(){
        this("SPADE",10);

    }
    Card(String kind, int num){
        this.kind = kind;
        this.num = num;

    }
    @Override
    public String toString(){
        return "kind : "+kind+" , num : "+num;
    }
    @Override
    public boolean equals(Object obj){ // 오버라이딩은 선언부가 일치해야 함,
        if (!(obj instanceof Card)){
            return false;
        }
        Card c = (Card)obj;
        return this.kind.equals(c.kind) && this.num == c.num;
    }
    //@Override
   // public int hashCode(){ // equals() 를 오버라이딩 해줬기 때문에 hashCode()도 오버라이딩 해줘야 합니다.
   //     return Objects.hash(kind,num); // Objects클래스는 객체와 관련된 융용한 메서드를 제공한다.
   // }


}

class JavaExercise_53 {
    public static void main(String[] args) { // Object 클래스의 toString() 메서드 오버라이딩 , equals(), hashCode() 오버라이딩
        Card c1 = new Card();
        Card c2 = new Card();

        System.out.println(c1.toString());
        System.out.println(c2.toString());

        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());

        System.out.println(c1.equals(c2));

    }
}

출력 결과 : 
kind : SPADE , num : 10
kind : SPADE , num : 10
1761291320
1451043227
true

hashCode() 메서드의 오버라이딩을 한 이후 
출력 결과 : 
kind : SPADE , num : 10
kind : SPADE , num : 10
-1842861210
-1842861210
true

위의 결과를 보면 hashCode() 메서드를 오버라이딩 하기 전에는 두 인스턴스의 해시코드 값이 다른 것을 볼 수 있지만 오버라이딩 한 결과는 두 해시코드의 값이 같은 것을 확인할 수 있다. 결론적으로 equals() 메서드를 오버라이딩 하면 두 객체의 주소값이 같아야 하기 때문에 hashCode() 메서드를 이용하여 두 객체의 해시코드를 같게 만들어줘야 한다.

0개의 댓글