동일성(Identity)
동일성은 두 객체가 동일한 메모리 위치를 참조하는지 여부
두 객체의 참조가 같은 객체를 가리키고 있는지를 확인하는 것
==
연산자를 사용하여 동일성을 비교한다
- Primitive 타입은 == 연산자를 사용했을 때 값이 같으면 true를 리턴
- 객체는 == 연산자를 사용했을 때 동일한 메모리 위치가 있으면 true를 리턴
동등성(Equality)
두 객체가 논리적으로 동일한 값을 가지는지
두 객체의 내용이 같은지
equals()
메서드를 사용하여 동등성을 비교
기본적으로 Object
클래스의 equals()
메서드는 ==
와 동일하게 동작하지만, 이를 재정의(overriding)하여 객체의 논리적 동등성을 비교할 수 있다
String str1 = new String("Hello");
String str2 = new String("Hello");
// 동등성 비교
if (str1.equals(str2)) {
System.out.println("str1 and str2 are equal");
} else {
System.out.println("str1 and str2 are not equal");
}
이 경우, str1
과 str2
는 같은 문자열 값을 가지므로 동등성 비교에서는 true
를 반환
주요 차이점
- 기준:
- 동일성은 객체의 참조(메모리 주소)가 같은지를 확인합니다.
- 동등성은 객체의 내용(값)이 같은지를 확인합니다.
- 사용되는 연산자/메서드:
- 동일성 비교에는
==
연산자를 사용합니다. - 동등성 비교에는
equals()
메서드를 사용합니다.
- 동일성 비교에는
- 적용 대상:
- 동일성은 객체의 참조 자체를 비교할 때 사용됩니다.
- 동등성은 객체의 논리적 상태나 값을 비교할 때 사용됩니다.
hashCode()
메서드
객체끼리 비교할 때에는 Java의 Object
클래스에서 정의된 equals()
와 hashCode()
메서드를 둘 다 재정의해 줘야 한다.
Java에서 hashCode()
메서드는 객체의 해시 코드를 반환하는 데 사용된다.
해시 코드는 정수 값으로, 해시 기반의 컬렉션(예: HashMap
, HashSet
)에서 객체를 빠르게 검색하고 저장하는 데 사용된다.
equals()
메서드와 hashCode()
메서드는 밀접한 관계가 있으며, 올바르게 동작하도록 함께 재정의해야 한다.
hashCode()
메서드의 역할
hashCode()
메서드는 객체의 해시 코드를 반환하며, 이는 객체의 메모리 주소를 기반으로 한 정수 값이다. 이 값은 객체를 해시 테이블에 저장하고 검색하는 데 사용된다.
equals()
와 hashCode()
의 관계
- 동등한 객체는 동일한 해시 코드를 가져야 한다
equals()
메서드에 의해 두 객체가 같다고 판단되면(a.equals(b) == true
), 두 객체의hashCode()
값은 동일해야 합니다 (a.hashCode() == b.hashCode()
).
- 동일한 해시 코드를 가지는 객체가 반드시 동등하지는 않다
- 두 객체의
hashCode()
값이 같다고 해서 반드시equals()
메서드가true
를 반환하는 것은 아니다. - 해시 코드는 대체로 고유한 편이지만 충돌이 발생할 수 있다
- 두 객체의
왜 hashCode()
를 재정의해야 하는가?
hashCode()
메서드를 재정의하지 않으면, Object
클래스의 기본 구현이 사용된다.
기본 구현은 객체의 메모리 주소를 기반으로 해시 코드를 생성하므로, 동등한 두 객체(equals()
가 true
를 반환하는 객체)의 해시 코드가 다를 수 있다.
따라서 해시 기반 컬렉션에서 올바르게 동작하지 않게 된다
hashCode()
메서드 재정의
import java.util.Objects;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public static void main(String[] args) {
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Alice", 30);
// 동일성 비교
if (p1 == p2) {
System.out.println("p1 and p2 are identical");
} else {
System.out.println("p1 and p2 are not identical");
}
// 동등성 비교
if (p1.equals(p2)) {
System.out.println("p1 and p2 are equal");
} else {
System.out.println("p1 and p2 are not equal");
}
// 해시 코드 비교
System.out.println("p1.hashCode(): " + p1.hashCode());
System.out.println("p2.hashCode(): " + p2.hashCode());
}
}
'TIL(Develop)' 카테고리의 다른 글
Java의 메모리 관리와 가비지 컬렉션 (0) | 2024.05.16 |
---|---|
Java 접근제어자 (0) | 2024.05.15 |
JPA 사용할때 쿼리가 복잡해지는 경우의 해결방안 (0) | 2024.05.15 |
Spring mvc 패턴 (0) | 2024.05.14 |
Spring JPA 상속 관계 (0) | 2024.05.10 |