소개
이 랩에서는 Java 에서 두 객체가 같은지 확인하는 방법을 배우게 됩니다. 객체 비교를 위해 == 연산자와 equals() 메서드를 사용하는 것의 근본적인 차이점을 살펴볼 것입니다.
먼저 내장된 equals() 메서드를 사용하여 객체를 비교하고 다양한 데이터 유형에서 해당 동작을 이해합니다. 그런 다음, 객체에 대한 논리적 동일성을 정의하기 위해 사용자 정의 클래스에서 equals() 메서드를 재정의하는 방법을 배우게 됩니다. 마지막으로, NullPointerException 오류를 방지하기 위해 동일성 검사를 수행할 때 null 객체를 처리하는 중요한 고려 사항을 다룰 것입니다.
equals() 메서드를 사용하여 동일성 확인
이 단계에서는 equals() 메서드를 사용하여 Java 에서 객체를 비교하는 방법을 살펴보겠습니다. == 연산자는 두 객체 참조가 메모리에서 정확히 동일한 객체를 가리키는지 확인하는 반면, equals() 메서드는 두 객체가 논리적으로 같은지, 즉 동일한 값이나 상태를 나타내는지 확인하도록 설계되었습니다.
이 개념을 시연하기 위해 간단한 Java 파일을 만들어 보겠습니다.
WebIDE 를 열고
~/project디렉토리에 있는지 확인합니다. 터미널 프롬프트를 보거나pwd를 입력하고 Enter 키를 눌러 확인할 수 있습니다.~/project디렉토리에EqualityDemo.java라는 새 파일을 만듭니다. 왼쪽의 파일 탐색기에서 마우스 오른쪽 버튼을 클릭하고 "New File"을 선택한 다음EqualityDemo.java를 입력하여 이 작업을 수행할 수 있습니다.편집기에서
EqualityDemo.java파일을 열고 다음 코드를 붙여넣습니다.public class EqualityDemo { public static void main(String[] args) { String str1 = new String("hello"); String str2 = new String("hello"); String str3 = str1; System.out.println("Comparing String objects:"); System.out.println("str1 == str2: " + (str1 == str2)); System.out.println("str1.equals(str2): " + str1.equals(str2)); System.out.println("str1 == str3: " + (str1 == str3)); System.out.println("str1.equals(str3): " + str1.equals(str3)); System.out.println("\nComparing primitive types (int):"); int num1 = 10; int num2 = 10; System.out.println("num1 == num2: " + (num1 == num2)); } }이 코드에서:
- 동일한 내용 ("hello") 을 가진 두 개의
String객체str1과str2를 생성하지만,new String()을 사용하여 메모리에 별도의 객체를 생성합니다. - 세 번째
String참조str3을 생성하고str1과 동일한 객체를 가리키도록 합니다. str1과str2, 그리고str1과str3을 비교하기 위해==와equals()를 모두 사용합니다.- 또한
==를 사용하여 기본int유형의 비교를 보여줍니다.equals()는 기본 유형이 아닌 객체에 사용된다는 점을 기억하십시오.
- 동일한 내용 ("hello") 을 가진 두 개의
EqualityDemo.java파일을 저장합니다 (Ctrl+S 또는 Cmd+S).WebIDE 하단에서 터미널을 엽니다.
다음 명령을 입력하고 Enter 키를 눌러 Java 프로그램을 컴파일합니다.
javac EqualityDemo.java오류가 없으면 출력이 표시되지 않습니다.
다음 명령을 입력하고 Enter 키를 눌러 컴파일된 프로그램을 실행합니다.
java EqualityDemo다음과 유사한 출력이 표시됩니다.
Comparing String objects: str1 == str2: false str1.equals(str2): true str1 == str3: true str1.equals(str3): true Comparing primitive types (int): num1 == num2: truestr1 == str2는 내용이 같더라도 메모리에서 다른 객체이므로false입니다. 그러나str1.equals(str2)는String클래스의equals()메서드가 문자열의 실제 내용을 비교하도록 재정의되었기 때문에true입니다.str1 == str3은str3이str1과 정확히 동일한 객체를 가리키기 때문에true입니다.이것은 Java 에서 객체를 비교할 때
==(참조 동일성) 와equals()(논리적 동일성) 의 주요 차이점을 보여줍니다. 기본 유형의 경우==는 값 비교에 사용됩니다.
사용자 정의 클래스에서 equals() 재정의
이전 단계에서 String 객체에 대한 equals() 메서드의 작동 방식을 살펴보았습니다. String 클래스는 내용에 따라 의미 있는 비교를 제공하기 위해 기본 equals() 메서드 (Object 클래스에서 상속됨) 를 이미 재정의했습니다.
그러나 사용자 정의 클래스를 만들 때 Object에서 상속된 기본 equals() 메서드는 단순히 == 연산자를 사용하므로 참조 동일성만 확인합니다. 사용자 정의 클래스의 객체를 해당 속성 (논리적 동일성) 을 기반으로 비교하려면 equals() 메서드를 직접 재정의해야 합니다.
이 단계에서는 간단한 Person 클래스를 만들고 해당 equals() 메서드를 재정의합니다.
WebIDE 에서
~/project디렉토리에 있는지 확인합니다.~/project디렉토리에Person.java라는 새 파일을 만듭니다.Person.java를 열고Person클래스에 대한 다음 코드를 붙여넣습니다.public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } // Default equals() method (inherited from Object) would only check reference equality // We need to override it to check for logical equality based on name and age @Override public boolean equals(Object obj) { // Step 1: Check if the objects are the same instance if (this == obj) { return true; } // Step 2: Check if the object is null or of a different class if (obj == null || getClass() != obj.getClass()) { return false; } // Step 3: Cast the object to the correct type Person person = (Person) obj; // Step 4: Compare the relevant attributes return age == person.age && name.equals(person.name); // Use equals() for String comparison } }이
Person클래스에서:name(String) 과age(int) 의 두 가지 개인 속성이 있습니다.- 이러한 속성을 초기화하는 생성자가 있습니다.
- 속성에 액세스하기 위한 getter 메서드가 있습니다.
equals()메서드를 재정의했습니다. 재정의된equals()내부의 단계를 살펴보겠습니다.if (this == obj): 이는 최적화입니다. 두 참조가 정확히 동일한 객체를 가리키는 경우, 확실히 같습니다.if (obj == null || getClass() != obj.getClass()): 비교할 객체가 null 인지 또는Person클래스의 인스턴스가 아닌지 확인합니다. 둘 중 하나라도 참이면 같을 수 없습니다.Person person = (Person) obj;: 일반Object를Person객체로 캐스팅하여name및age속성에 액세스할 수 있습니다.return age == person.age && name.equals(person.name);: 이는 논리적 비교의 핵심입니다.age가 동일한지 (기본 int 의 경우==사용) 와name이 동일한지 (String 객체의 경우equals()사용) 확인합니다.
Person.java파일을 저장합니다.이제 재정의된
equals()메서드를 테스트하기 위해PersonEqualityDemo.java라는 다른 파일을 만들어 보겠습니다.~/project디렉토리에 이 파일을 만듭니다.PersonEqualityDemo.java를 열고 다음 코드를 붙여넣습니다.public class PersonEqualityDemo { public static void main(String[] args) { Person person1 = new Person("Alice", 30); Person person2 = new Person("Alice", 30); Person person3 = new Person("Bob", 25); Person person4 = person1; System.out.println("Comparing Person objects:"); System.out.println("person1 == person2: " + (person1 == person2)); System.out.println("person1.equals(person2): " + person1.equals(person2)); System.out.println("person1 == person3: " + (person1 == person3)); System.out.println("person1.equals(person3): " + person1.equals(person3)); System.out.println("person1 == person4: " + (person1 == person4)); System.out.println("person1.equals(person4): " + person1.equals(person4)); } }이 데모 클래스에서는 여러
Person객체를 만들고==와 재정의된equals()메서드를 사용하여 비교합니다.PersonEqualityDemo.java파일을 저장합니다.터미널을 엽니다.
~/project에 있는지 확인합니다.두 Java 파일을 모두 컴파일합니다. 한 번에 여러 파일을 컴파일할 수 있습니다.
javac Person.java PersonEqualityDemo.java그러면
Person.class및PersonEqualityDemo.class파일이 생성됩니다.데모 프로그램을 실행합니다.
java PersonEqualityDemo다음과 유사한 출력이 표시됩니다.
Comparing Person objects: person1 == person2: false person1.equals(person2): true person1 == person3: false person1.equals(person3): false person1 == person4: true person1.equals(person4): true예상대로
person1 == person2는 서로 다른 객체이므로false이지만, 재정의된 메서드에 따라name과age가 같으므로person1.equals(person2)는true입니다.person1과person3은 두 비교 모두에서 같지 않습니다.person1과person4는 동일한 객체를 참조하므로 두 비교 모두에서 같습니다.equals()메서드를 재정의하면 메모리 위치뿐만 아니라 논리적 상태를 기반으로 사용자 정의 클래스의 객체에 대한 "같음"의 의미를 정의합니다.
동등성 비교 시 Null 객체 처리
이전 단계에서 Person 클래스에서 equals() 메서드를 성공적으로 재정의하여 속성을 기반으로 객체를 비교했습니다. 견고한 equals() 메서드를 작성하는 데 중요한 측면 중 하나는 잠재적인 null 값을 처리하는 것입니다. null 객체에서 메서드를 호출하려고 하면 Java 에서 흔히 발생하는 오류인 NullPointerException이 발생합니다.
Person.java에서 재정의된 equals() 메서드는 이미 null에 대한 검사를 포함하고 있습니다: if (obj == null || getClass() != obj.getClass()). 이는 비교할 객체가 null인 경우를 처리하는 표준 방법입니다.
이 단계에서는 객체를 null과 비교할 때 어떤 일이 발생하는지 시연하고 equals() 메서드가 이를 올바르게 처리하는지 확인합니다.
WebIDE 에서
~/project디렉토리에 있는지 확인합니다.이전 단계에서 생성한
PersonEqualityDemo.java파일을 엽니다.기존 비교 문 뒤에 다음 줄을
main메서드에 추가합니다.System.out.println("\nComparing with null:"); System.out.println("person1.equals(null): " + person1.equals(null));이 코드는 단순히
person1과null의 비교를 추가합니다.PersonEqualityDemo.java파일을 저장합니다.터미널을 엽니다.
~/project에 있는지 확인합니다.수정된
PersonEqualityDemo.java파일을 컴파일합니다.javac PersonEqualityDemo.java변경한 파일만 다시 컴파일하면 된다는 점을 기억하십시오. 이 단계에서
Person.java는 변경되지 않았으므로PersonEqualityDemo.java만 컴파일하면 됩니다.컴파일된 프로그램을 실행합니다.
java PersonEqualityDemo이제 이전 출력 다음에 null 과의 새로운 비교가 표시됩니다.
Comparing Person objects: person1 == person2: false person1.equals(person2): true person1 == person3: false person1.equals(person3): false person1 == person4: true person1.equals(person4): true Comparing with null: person1.equals(null): false출력
person1.equals(null): false는 재정의된equals()메서드가null과의 비교를 올바르게 처리하고NullPointerException을 발생시키지 않고false를 반환함을 확인합니다. 이는Person클래스의equals()메서드에서if (obj == null || getClass() != obj.getClass())줄이obj의 속성에 액세스하기 전에null을 확인하기 때문입니다.null을 처리하는 것은 Java 에서 견고한 코드를 작성하는 데 중요한 부분이며, 특히 객체 비교를 처리할 때 더욱 그렇습니다. 재정의된equals()메서드의 시작 부분에 항상null검사를 포함하십시오.
요약
이 Lab 에서는 Java 에서 두 객체가 같은지 확인하는 방법을 배웠습니다. 참조 동일성을 확인하는 == 연산자와 논리적 동일성을 확인하는 equals() 메서드의 차이점을 이해하는 것으로 시작했습니다. String 객체와 기본 유형을 사용하여 이를 시연하고 객체에 대해 ==가 equals()와 어떻게 다르게 동작하는지 관찰했습니다.
그런 다음 객체 동일성에 대한 자체 기준을 정의하기 위해 사용자 정의 클래스에서 equals() 메서드를 재정의하는 방법을 살펴보았습니다. 이는 사용자 정의 객체가 메모리 위치가 아닌 내용 또는 상태를 기반으로 비교되도록 보장하는 데 중요합니다. 마지막으로, NullPointerException을 방지하고 강력한 동일성 검사를 보장하기 위해 equals() 메서드 내에서 null 객체를 처리하는 것의 중요성을 배웠습니다.



