윤개발
Java의 Equals와 Hashcode 본문
Java를 처음 접할때 배우는 메소드임에도 잘 모르고 쓰는 경우가 많은 Equals와 Hashcode에 대해서 알아보자.
두 메소드는 모든 객체의 부모인 Object 클래스에 구현되어있다. Objcect의 구현된 소스코드를 살펴보자.
// Indicates whether some other object is "equal to" this one.
public boolean equals(Object obj) {
return (this == obj);
}
Object 클래스에 구현된 equals 클래스이다. 생각보다 코드가 단순하고 객체 자체가 같은지를 비교하는 코드이다.
다음은 hashcode이다. hashcode는 따로 작성된 코드가 없이 native라는 코드가 붙어있다.
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by {@link java.util.HashMap}.
**/
public native int hashCode();
hashcode는 항상은 아니지만 힙에 저장되어있는 객체의 고유 주소값을 반환한다.
두 메서드는 오버라이딩해서 쓸수가 있다. 하지만 이펙티브 자바의 "[ITEM10] equals는 일반 규약을 지켜 재정의하라." 에서는 재정의를 하지 않는것을 추천한다.
equals 메서드는 재정의하기 쉬워보이지만 곳곳에 함정이 있어 큰 문제가 될 수 있다. 아래 상황에 해당한다면 재정의 하지 않는것이 최선이다.
- 각 인스턴스가 본질적으로 고유하다. 값을 표현하는게 아니라 개체를 표현하는 클래스가 해당된다.
- 인스턴스의 논리적 동치성을 검사할 일이 없다.
- 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는다.
- 클래스가 private 여서 equals를 호출할 일이 없다.
결론적으로 두 메서드 다 객체가 동일한지 보는 것이다.
단 객체의 값이 동일한지 알고 싶을 경우에는 equals 함수를 오버라이딩 할 수 있다.
Null체크를 하고, 타입이 같은지 확인하고, 값을 확인한다.
이렇게 equals 가 오버라이딩 된 객체는 String 객체가 있다.
String 객체는 값이 같은지 비교하는 오버라이딩 함수가 작성되어있다.
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
또한 equals를 재정의 하였다면 hashcode도 재정의 하여야한다.
equals를 통해 같은 값으로 나왔다면 hashcode의 결과도 같은 값으로 나와야하기 때문이다.
hashset 과 같은 함수에 저장을 해야할 경우 equals에서 동등하다고 나왔어도 hashcode를 오버라이딩 하지 않으면
동일한 객체로 인식하지 못해 2가지가 모두 삽입된다.
'백엔드 > Java' 카테고리의 다른 글
DIP 아키텍처 설계 (0) | 2021.08.03 |
---|---|
Java Garbage Collection 이란? (0) | 2020.11.12 |