equals 와 == 차이

서버란·2024년 8월 30일

자바 궁금증

목록 보기
2/35

자바에서는 객체나 값을 비교할 때 두 가지 중요한 방법이 있습니다. 바로 == 연산자와 equals() 메서드입니다.
이 두 방법은 비교 대상이 기본 데이터 타입인지, 참조 타입인지에 따라 다르게 동작하기 때문에, 각각의 특성을 정확히 이해하고 사용하는 것이 중요합니다. 이번 글에서는 이 두 가지 방법의 차이점과 사용 예시를 정리해보겠습니다.

1. == 연산자

기본 데이터 타입(Primitive Type)의 비교

기본 데이터 타입, 예를 들어 int, char, boolean 등의 값을 비교할 때는 == 연산자를 사용합니다. 이 연산자는 두 값이 동일한지 여부를 판단합니다.

int a = 5;
int b = 5;
System.out.println(a == b);  // true, 값이 같음

위의 예시에서 a와 b는 동일한 값을 가지므로 == 연산자는 true를 반환합니다.

참조 타입(Reference Type)의 비교

참조 타입에서는 == 연산자가 두 객체의 참조(메모리 주소)가 같은지를 비교합니다. 즉, 두 객체가 같은 메모리 공간을 가리키는지 확인합니다.

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가 출력됩니다.

2. equals() 메서드

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() 메서드
  • 객체의 내용(값)을 비교합니다.
  • Object 클래스에서는 참조를 비교하지만, 여러 클래스에서 재정의하여 값을 비교하는 방식으로 사용됩니다.

결론

  • 기본 데이터 타입에서는 == 연산자를 사용하여 값을 비교하면 됩니다.
  • 참조 타입에서는 두 객체가 같은 메모리 공간을 참조하는지 확인하려면 == 연산자를 사용하고, 두 객체의 값이 같은지 확인하려면 equals() 메서드를 사용하는 것이 올바른 방법입니다.

참조 타입에서 객체의 내용을 비교해야 할 때 == 연산자를 사용하면 예상과 다른 결과를 얻을 수 있으니, 객체의 값을 비교할 때는 항상 equals() 메서드를 사용하는 습관을 들이는 것이 좋습니다.


Q1: 자바에서 기본 데이터 타입과 참조 타입의 차이점은 무엇인가요?

기본 데이터 타입(Primitive Type)과 참조 타입(Reference Type)은 메모리 저장 방식과 비교 방법에서 차이가 있습니다.

  • 기본 데이터 타입: int, char, boolean과 같은 기본 데이터 타입은 실제 값이 메모리에 직접 저장됩니다. 따라서 값 자체를 비교할 때 == 연산자를 사용하면 값이 동일한지 비교합니다.

예:

int a = 5;
int b = 5;
System.out.println(a == b);  // true, 값이 동일
  • 참조 타입: String, Array, Object와 같은 참조 타입은 실제 데이터가 저장된 메모리 주소(참조)를 가리키는 방식입니다. 두 객체가 같은 메모리 주소를 가리키고 있을 때만 == 연산자는 true를 반환합니다.

예:

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);  // false, 서로 다른 객체

참조 타입은 객체의 내용(값)을 비교하려면 equals() 메서드를 사용해야 합니다.

Q2: String과 같은 불변 객체의 특성은 비교 연산에서 어떤 영향을 미칠까요?

String은 불변 객체(immutable object)로, 한 번 생성된 이후에는 그 값을 변경할 수 없습니다. 불변 객체의 이러한 특성은 비교 연산에서 다음과 같은 두 가지 영향을 미칩니다.

  1. 리터럴 문자열 비교에서 최적화: 자바에서는 동일한 문자열 리터럴을 사용하는 경우, 같은 메모리 주소를 가리키도록 내부적으로 최적화(String Pool)를 수행합니다. 따라서 리터럴 문자열을 == 연산자로 비교하면 true가 나올 수 있습니다.

예:

String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);  // true, 같은 메모리 참조
  1. new 키워드로 생성된 객체: new 키워드로 String 객체를 생성하면 매번 새로운 메모리 공간을 할당받기 때문에, 내용은 같아도 == 연산자로 비교하면 false가 나옵니다. 이때는 equals() 메서드를 사용해야 합니다.

예:

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() 메서드를 재정의하면, 객체의 참조가 아닌 객체의 값(속성)을 기반으로 동등성을 비교할 수 있습니다.

profile
백엔드에서 서버엔지니어가 된 사람

0개의 댓글