==
비교를 통해 판별할 수 있으며 참조하고 있는 메모리 주소 값이 같다면 동일하다고 할 수 있음
equals()
비교를 통해 판별할 수 있으며 참조하고 있는 메모리 주소 값이 달라도 내용이 같으면 동등하다고 할 수 있음
Car a1 = new Car("A") Car a2 = new Car("A") System.out.println(a1 == a2) // false System.out.println(a1.equals(a2)) // false // 사실 Object의 equals도 == 과 다르지 않음 public boolean equals(Object obj) { return (this == obj); }
컴퓨터 입장에서는
a1
객체가 저장되어 있는 힙 영역의 주소값과a2
객체가 저장되어 있는 힙 영역의 주소값이 다르기 때문에 당연히 다른 객체이다.하지만 사람이 봤을 땐 같은 데이터로 생각할 수도 있을 것이다. 그렇게 하기 위해서는
equals()
를 오버라이딩하면 된다.// intelliJ를 사용한 오버라이딩 @Override public boolean equals(Object object) { if (this == object) return true; if (object == null || getClass() != object.getClass()) return false; Book book = (Book) object; return Objects.equals(name, book.name) && Objects.equals(author, book.author); }
equals()
를 오버라이딩 한 후에 다시 비교를 해보면 같다고 나오게 된다.System.out.println(a1.equals(a2)); // true
그런데 인텔리제이를 사용하여
equals()
를 오버라이딩하면hashcode()
도 같이 오버라이딩이 된다. 왜 그런것일까?// equals 아래에 hashcode의 오버라이딩도 같이 생김 @Override public int hashCode() { return Objects.hash(name); }
결론부터 말하자면 hash값을 사용하는 컬렉션(HashSet, HashMap, HashTable)을 사용할 때 문제가 발생한다. hash값을 사용하는 컬렉션은 객체가 논리적으로 같은지 비교할 때 다음과 같은 과정을 거친다.
hashcode란 객체를 식별하는 하나의 고유 정수값을 의미하는데 hashcode()의 리턴 값이 일치하고 equals()의 리턴 값도 일치해야 같은 객체라고 판단한다.하지만 hashcode()를 오버라이딩 하지 않으면 equals() 비교도 하기 전에 다른 객체로 판단되는 것이다.
hash값을 사용하는 컬렉션을 쓰지 않는다면 hashcode()의 오버라이딩은 필요없지 않은가?
라고 생각할 수 있다. 하지만, 요구사항이 변하거나 다른 동료가 hash값을 사용하는 컬렉션을 사용할 수도 있기 때문에 같이 오버라이딩 해주는 것이 안전하다고 생각한다.