반응형
자바에서 객체를 비교할 때 혼동되기 쉬운 두 가지 개념 : 동등성(Equality)과 동일성(Identity)
동등성(Equality)
- 동등성은 두 객체가 논리적으로 동일한 값을 가지고 있는지를 비교
- primitive type : 값 자체를 비교
- reference type : 객체의 내부 상태(속성 값)를 비교
동일성(Identity)
- 동일성은 두 참조 변수가 메모리 상에서 정확히 같은 객체를 가리키는지를 비교
- 두 변수가 힙 메모리에서 동일한 주소를 참조하는지를 비교하는 것
equals()와 == 연산자
==
연산자- primitive type에 사용: 값 자체를 비교(동등성)
- reference type에 사용: 두 참조 변수가 같은 메모리 주소를 가리키는지 비교(동일성)
@Test
void comparePrimitive() {
int a = 5;
int b = 5;
assertThat(a == b).isTrue();
}
@Test
void compareReference() {
String s1 = new String("Hello");
String s2 = new String("Hello");
assertThat(s1 == s2).isFalse();
}
equals()
메서드- Object 클래스의 기본 equals() 구현은 ==와 동일하게 동작
- 객체 간 동등성 비교를 위해서는 equals() 메서드를 오버라이딩해야 한다.
class Object { public boolean equals(Object obj) { return (this == obj); } }
- 객체 간 동등성 비교를 위해서는 equals() 메서드를 오버라이딩해야 한다.
- Object 클래스의 기본 equals() 구현은 ==와 동일하게 동작
@Test
void compareReference() {
String s1 = new String("Hello");
String s2 = new String("Hello");
assertThat(s1.equals(s2)).isTrue();
}
hashCode()
- 객체의 해시코드 값을 정수로 반환하는 메서드
- 기본 구현은 객체의 메모리 주소를 기반으로 해시 값을 계산
HashMap
,HashSet
,Hashtable
등 해시 기반 컬렉션에서 객체를 저장하고 검색하는 데 사용equals()
가 true를 반환하는 두 객체는 반드시 같은hashCode()
를 반환해야 한다.
// equals()만 오버라이딩
class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person person)) return false;
if (age != person.age) return false;
return Objects.equals(name, person.name);
}
}
@Test
void nonHashCode() {
Person p1 = new Person("Kim", 25);
Person p2 = new Person("Kim", 25);
// hashCode()를 오버라이딩하지 않아서 다른 해시코드를 가진다.
assertThat(p1.hashCode() == p2.hashCode()).isFalse();
HashSet<Person> set = new HashSet<>();
set.add(p1);
set.add(p2);
// 같은 객체
assertThat(set.size()).isEqualTo(2);
}
- equals() 와 hashcode() 둘 다 오버라이딩 해줘야 해시 컬렉션이 올바르게 동작한다.
반응형