public String toString() { // Object 클래스의 toString() 메서드
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
사실 문자열 파트를 공부하면서 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()도 오버라이딩 해줘야한다.
위의 말이 참 길었다. 코드로 결과를 보면 더 쉽게 이해할 수 있다.
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() 메서드를 이용하여 두 객체의 해시코드를 같게 만들어줘야 한다.