equals()와 hashCode()
Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 42번째.
Java에서 객체를 비교할 때 == 연산자는 두 참조가 같은 메모리 위치를 가리키는지 확인합니다. 객체의 실제 내용을 비교하려면 equals() 메서드를 재정의해야 합니다.
public class Person {
private String name;
private int 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 && name.equals(person.name);
}
}equals() 메서드는 표준 패턴을 따릅니다. 먼저 같은 객체인지 확인하고, 그런 다음 타입을 검증한 후, 마지막으로 관련 필드를 비교합니다.
equals()를 재정의할 때마다 hashCode()도 반드시 재정의해야 합니다. 이는 Java의 규약입니다. 서로 같은 객체는 해시 코드도 같아야 합니다. HashMap 및 HashSet과 같은 해시 기반 컬렉션은 올바르게 작동하기 위해 이 규칙에 의존합니다.
@Override
public int hashCode() {
return Objects.hash(name, age);
}Objects.hash() 유틸리티 메서드는 equals()에서 사용하는 것과 동일한 필드로 해시 코드를 생성합니다. 두 Person 객체의 이름과 나이가 같으면 서로 같은 것으로 간주되어 동일한 해시 코드를 생성하며, 컬렉션에서 일관되게 동작하도록 합니다.
챌린지
쉬움객체 동등성을 올바르게 구현하는 학생 기록 시스템을 만들어 봅시다. 메모리에서 같은 객체인지와 관계없이 학생 ID와 이름이 같으면 두 학생을 같은 것으로 간주하는 Student 클래스를 만들 것입니다.
코드를 두 파일로 나눕니다.
Student.java: 학생을 나타내는 클래스를 만들고, 비공개 필드 세 개를 선언합니다:studentId(String),name(String),gpa(double). 모든 필드를 초기화하는 생성자와 각 필드의 getter 메서드를 포함합니다.equals()메서드를 재정의하여studentId와name이 모두 같을 때 두 Student 객체를 같은 것으로 간주하도록 합니다. 표준 패턴을 따르세요. 같은 참조인지 확인하고, null 및 타입을 확인한 다음, 해당 필드를 비교합니다.equals()에서 사용한 것과 같은 필드를 사용해Objects.hash()로hashCode()메서드를 재정의합니다. 파일 맨 위에java.util.Objects를 import하는 것을 잊지 마세요.Main.java: 학생 객체를 비교하여 Student 클래스를 실제로 사용해 봅니다. 두 학생을 나타내는 입력 여섯 개를 받습니다. 첫 번째 학생의 ID, 이름, GPA에 이어 두 번째 학생의 ID, 이름, GPA가 입력됩니다.두 Student 객체를 만든 다음, 세 가지 비교를 수행하고 결과를 출력합니다.
Same reference:를 출력한 뒤 첫 번째 학생이 자기 자신과 같은지 여부를 출력합니다 (항상 true여야 합니다).Content equality:를 출력한 뒤 첫 번째 학생과 두 번째 학생이 같은지 여부를 출력합니다 (equals 구현에 따름).Hash codes match:를 출력한 뒤 두 학생의 해시 코드가 같은지 여부를 출력합니다.
입력은 여섯 개입니다. 첫 번째 학생의 ID (String), 첫 번째 학생의 이름 (String), 첫 번째 학생의 GPA (double), 두 번째 학생의 ID (String), 두 번째 학생의 이름 (String), 두 번째 학생의 GPA (double)가 입력됩니다.
두 학생의 ID와 이름이 일치하면 equals()가 true를 반환하고 해시 코드도 일치한다는 점에 주목하세요. 이것이 반드시 지켜야 하는 규약입니다!
직접 해보기
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 첫 번째 학생의 데이터 읽기
String id1 = scanner.nextLine();
String name1 = scanner.nextLine();
double gpa1 = scanner.nextDouble();
scanner.nextLine(); // 줄바꿈 문자 소비
// 두 번째 학생의 데이터 읽기
String id2 = scanner.nextLine();
String name2 = scanner.nextLine();
double gpa2 = scanner.nextDouble();
// TODO: 입력 데이터를 사용하여 Student 객체 두 개 생성
// TODO: "Same reference: "를 출력한 다음 student1이 자기 자신과 같은지 출력
// TODO: "Content equality: "를 출력한 다음 student1과 student2가 같은지 출력
// TODO: "Hash codes match: "를 출력한 다음 두 학생의 해시 코드가 같은지 출력
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조7특별한 메서드와 Object 클래스
toString() 메서드equals()와 hashCode()clone() 메서드compareTo()와 ComparableComparator 인터페이스요약 - 커스텀 정렬직접 연습해 보세요: 온라인 Java 컴파일러