[JAVA] equals & hashCode

신명철·2022년 2월 25일
0

JAVA

목록 보기
1/14

객체 비교 (equals() 와 ==)

== 비교 연산자

==는 동등성을 비교한다. 즉, 객체의 참조값(주소값)이 서로 같은지를 검사한다. 두 객체가 서로 같은 객체인지를 판별하는 것이다.

원시 타입에 == 를 사용할 수 있는 이유

Java Runtime Data Area 의 Stack 영역에 변수가 저장된다. 해당 변수에 저장된 상수는 Runtime Constant Pool 에 저장되어 있고, Stack 의 변수 선언부는 해당 Runtime Constant Pool 의 주소값을 가지게 되는 것이다.
만약 서로 다른 두 변수가 같은 상수 값을 가진다면 Runtime Constant Pool 에 동일한 주소값을 가지게 되는 것이다. 그렇기 때문에 ==를 이용한 주소값 비교가 가능한 것이다.

equals()

Object 클래스의 equals() 는 두 객체가 서로 동일한지를 검사하기 위해 사용된다.

public boolean equals(Object obj) {
	return (this == obj); 
}
  • 두 객체의 참조값이 서로 같은지를 확인한다

2개의 서로 같은 문자열을 생성해서 이를 비교한다고 생각해보자. 이 2개의 문자열은 서로 다른 메모리 상에 할당될 것이다. 그런데 equals()를 사용하면 true를 반환한다. 그 이유는 String.class 가 이 equals()메소드를 오버라이딩해 논리적으로 동등한지를 비교하기 때문이다.

논리적으로 동등하다는 의미는, 두 객체가 참조값이 다르더라도 내부 value 가 서로 동일하다는 것을 의미한다.

hashCode()

hashCode()는 객체의 메모리 주소 값을 이용해 해시코드를 만들어 반환한다. 이 해시코드는 객체를 서로 식별하기 위해서 사용된다.
HashSet, HashMap, HashTable은 이 hashCode()를 이용해서 두 객체가 서로 동등한지를 판단하고 중복된 데이터의 저장을 허용하지 않는다.


equals() Override의 필요성

만약 두 객체를 equlas() 연산을 통해 비교한다고 가정해보자.

Book book1 = new Book();
Book book2 = new Book();

book1.setId(1);
book2.setId(1);

book1.eqauls(book2); // return false

위 두 객체 book1,book2 는 서로 같은 id 값을 가지고 있기 때문에 논리적으로 동등한 객체이다.
하지만 두 객체를 equals() 메소드를 통해 비교한다면 false를 반환한다. 두 객체의 참조 값이 다르기 때문이다. 그렇기 때문에 equlas()를 오버라이드해서 논리적으로 동등한 객체인지를 판별할 필요가 있다.

hashCode() Override의 필요성

위에서 언급했듯 Hash 관련 컬렉션 프레임워크는 hashCode()를 이용해 해시코드를 가지고 두 객체를 판별한다.
위의 예시를 적용한다면 두 객체 book1,book2는 서로 다른 객체이기 때문에 논리적으로 동등하지만 같은 메모리 상에 존재하지 않기 때문에 hashCode()를 사용하는 컬렉션에 중복된 채로 존재할 것이다.
따라서 아래와 같이 hashCode()를 재정의할 필요가 있다.

@Override
public int hashCode(){
	final int PRIME = 17;
    return PRIME + getId();
}
  • 위와 같은 작업을 거치면 book1book2는 서로 같은 객체로 판별되어 1개의 데이터만 저장될 것이다.
profile
내 머릿속 지우개

0개의 댓글