[JAVA] Equals & HashCode 오버라이드

유동우·2024년 1월 13일
0

자바 기본

목록 보기
3/4
post-thumbnail

Equals

자바 교재를 보며 기본부터 복기하던 중 의문점이 생겼다
Collecion 파트를 보고 있었고, HashSet에서 궁금점이 시작되었다.

HashSet<String> hashSet = new HashSet<>();

hashSet.add(new String("abc"));
hashSet.add(new String("awe"));
hashSet.add(new String("qwe"));
hashSet.add(new String("ttgar"));
hashSet.add("ttgar");

위 코드는 String 클래스에 객체가 동일한 경우에 대한 처리 방법이 이미 구현되어 있기 때문에 중복된 값이 hashSet에 들어가지 않는다 (메서드 오버라이드)

옛날에 배웠던 쉬운 예제를 간단히 복습해보자

String s1 = "Hello";
String s2 = "Hello";

System.out.println(s1 == s2); // 주소 비교 false
System.out.println(s1.equals(s2)); // 값 비교 true

위 처럼 String 변수에서는 == 비교와 equals 에 차이가 존재한다.

하지만 객체에서는 둘 다 같은 기능을 하게 된다.

Person person1 = new Person("홍길동");
Person person2 = new Person("홍길동");

System.out.println(person1 == person2);  
System.out.println(person1.equals(person2)) 

즉, 위 결과값은 모두 false 를 출력할 것이다.

person1 과 person2 모두 서로 다른 객체를 초기화해서 힙영역에 저장하고 있으니 당연히 false가 맞다.

이때 사람이 판단하기에 두 값은 같은 것이므로 같다고 구현을 하기 위해서는 메서드를 오버라이드 해주면 된다.

public boolean equals(Object obj) {
	if (this == obj) return true; 
	if (!(o instanceof Person)) return false; 
	
    Person person = (Person) o; 
	return Objects.equals(this.name, person.name); 
}

위와 같은 원리로 String 클래스 또한 재정의 되어있기 때문에
문자열 값을 비교할 수가 있는 것이다.


Hashcode

해시코드는 간단히 말하면 주소값으로 만든 객체의 고유한 숫자값이다.

Person p1 = new Person("홍길동");
Person p2 = new Person("홍길동");

System.out.println(p1.hashCode()); 
System.out.println(p2.hashCode());

서로 다른 객체의 해시코드 값은 분명히 다른값이 나올 것이다.

Object 클래스에 정의된 hashCode() 메서드를 살펴보자

public class Object{
	public native int hashCode();
}

native : OS가 소유한 메소드를 의미한다.
즉, native 코드중 하나가 hashCode()이고 이 native 코드 or C 같은 저수준 언어로 작성된 코드를 JVM에 적재하여 실행시키는 머신이 JNI (Java Native Interface) 이다.

이제 이 포스팅의 핵심이 등장한다

equals() 메서드를 재정의 할 경우 hashCode() 메서드 또한 재정의를 해줘야한다.

equals() 결과가 true 인 두 객체에 대해서는 해시코드의 값이 반드시 같아야 하기 때문이다 .

hashCode() 메서드를 재정의 하지 않으면 Hash 관련한 Collection을 사용할 때 문제가 발생한다.

hashCode( ) (true) -> equals( ) (true) -> 동등객체 순으로 판단하기 때문이다.

profile
효율적이고 꾸준하게

0개의 댓글