자바에서는 객체나 값을 비교할 때 두 가지 중요한 방법이 있습니다. 바로 == 연산자와 equals() 메서드입니다.
이 두 방법은 비교 대상이 기본 데이터 타입인지, 참조 타입인지에 따라 다르게 동작하기 때문에, 각각의 특성을 정확히 이해하고 사용하는 것이 중요합니다. 이번 글에서는 이 두 가지 방법의 차이점과 사용 예시를 정리해보겠습니다.
기본 데이터 타입, 예를 들어 int, char, boolean 등의 값을 비교할 때는 == 연산자를 사용합니다. 이 연산자는 두 값이 동일한지 여부를 판단합니다.
int a = 5;
int b = 5;
System.out.println(a == b); // true, 값이 같음
위의 예시에서 a와 b는 동일한 값을 가지므로 == 연산자는 true를 반환합니다.
참조 타입에서는 == 연산자가 두 객체의 참조(메모리 주소)가 같은지를 비교합니다. 즉, 두 객체가 같은 메모리 공간을 가리키는지 확인합니다.
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2); // false, 다른 객체(메모리 주소 다름)
이 예시에서 str1과 str2는 동일한 문자열 값을 가지지만, 각각 다른 객체로 생성되었기 때문에 메모리 주소가 다릅니다. 따라서 == 연산자는 false를 반환합니다.
String str3 = str1;
System.out.println(str1 == str3); // true, 같은 객체(참조 동일)
반면, str3은 str1과 동일한 객체를 참조하므로 true가 출력됩니다.
equals() 메서드는 객체의 내용(값)을 비교하기 위해 사용됩니다. 기본적으로는 Object 클래스에 정의되어 있으며, 두 객체의 참조가 동일한지 비교하지만, 많은 클래스(String, Integer 등)들은 이 메서드를 재정의하여 객체의 값을 비교하도록 만듭니다.
사용 예시
String str1 = "test";
String str2 = "test";
String str3 = new String("test");
String str4 = new String("test");
System.out.println(str1 == str3); // false, 참조가 다름
System.out.println(str1.equals(str3)); // true, 내용이 같음
위 예시에서 str1과 str3은 서로 다른 객체이지만, equals() 메서드를 사용하면 그 안에 담긴 문자열 값이 동일하기 때문에 true를 반환합니다.
== 연산자
참조 타입에서 객체의 내용을 비교해야 할 때 == 연산자를 사용하면 예상과 다른 결과를 얻을 수 있으니, 객체의 값을 비교할 때는 항상 equals() 메서드를 사용하는 습관을 들이는 것이 좋습니다.
Q1: 자바에서 기본 데이터 타입과 참조 타입의 차이점은 무엇인가요?
기본 데이터 타입(Primitive Type)과 참조 타입(Reference Type)은 메모리 저장 방식과 비교 방법에서 차이가 있습니다.
예:
int a = 5;
int b = 5;
System.out.println(a == b); // true, 값이 동일
예:
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2); // false, 서로 다른 객체
참조 타입은 객체의 내용(값)을 비교하려면 equals() 메서드를 사용해야 합니다.
Q2: String과 같은 불변 객체의 특성은 비교 연산에서 어떤 영향을 미칠까요?
String은 불변 객체(immutable object)로, 한 번 생성된 이후에는 그 값을 변경할 수 없습니다. 불변 객체의 이러한 특성은 비교 연산에서 다음과 같은 두 가지 영향을 미칩니다.
예:
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // true, 같은 메모리 참조
예:
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2); // false, 다른 객체
System.out.println(str1.equals(str2)); // true, 값이 동일
Q3: 커스텀 객체를 비교할 때 equals() 메서드를 재정의하는 이유는 무엇인가요?
답변:
자바의 기본 Object 클래스에서 제공하는 equals() 메서드는 두 객체의 참조(메모리 주소)가 같은지를 비교합니다. 하지만, 커스텀 객체를 생성할 때는 참조가 아닌 객체의 실제 데이터(속성 값)를 기준으로 비교해야 할 때가 많습니다.
예를 들어, 두 사람 객체(Person)가 같은 이름과 나이를 가질 때 동일한 객체로 간주하고 싶다면, equals() 메서드를 재정의해야 합니다. 재정의된 equals() 메서드는 객체의 특정 필드(예: name, age)를 기반으로 비교하게 됩니다.
예시:
class Person {
String name;
int age;
// equals() 메서드 재정의
@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);
}
}
위와 같이 equals() 메서드를 재정의하면, 객체의 참조가 아닌 객체의 값(속성)을 기반으로 동등성을 비교할 수 있습니다.