비교란 무엇일까? (동등성/동일성)

ChoRong0824·2025년 3월 19일
0

Web

목록 보기
47/51
post-thumbnail

Eqaulity 와 Identity
이 두 개념은 == 연산자와 equals() 메서드를 통해 구현되며, 그 차이를 명확히 아는 것이 중요하다고 생각됩니다.

Identity

동일성이란 ?

  • 두 객체의 메모리 주소가 같은지 비교하는 것.
  • == 연산자를 사용하여 비교합니다.
  • 동일한 객체인지 확인할 때 사용

예제

public class IdentityExample {
    public static void main(String[] args) {
        String str1 = new String("hello");
        String str2 = new String("hello");

        System.out.println(str1 == str2); // false (다른 객체)

        String str3 = "hello";
        String str4 = "hello";

        System.out.println(str3 == str4); // true (String Pool 내부에서 같은 객체 공유)
    }
}
/*
str1 과 str2 는 new 키워드를 사용하여 새로운 객체를 생성했기 때문에 메모리 주소가 다릅니다.
즉, str1 == str2 는 false 가 나옵니다.
str3 과 str4 는 String Pool 에 저장된 동일한 객체를 참조하므로 str3 == str4 는 true 입니다.
*/

Equality

동등성이란 ?

  • 객체가 같은 값을 가지고 있는지 비교하는 것 입니다.
  • equals() 메서드를 사용하여 비교합니다.
  • equals() 메서드는 기본적으로 Object 클래스에서 제공하는 메서드이며, Object의 기본 구현은 ==과 동일하게 동작합니다.
    하지만 대부분의 클래스는 이를 오버라이드하여 논리적으로 같은 값을 가지는지를 비교합니다.

예제

public class EqualityExample {
    public static void main(String[] args) {
        String str1 = new String("hello");
        String str2 = new String("hello");

        System.out.println(str1.equals(str2)); // true (문자열 값이 같음)

        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");

        System.out.println(p1.equals(p2)); // false (Person 클래스에서 equals() 오버라이드하지 않으면 기본적으로 == 비교)
    }
}

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }
}
/*
- str1.equals(str2) 는 true 가 나오지만 p1.equals(p2) 는 false 가 나옵니다.
- String 클래스는 equals()를 오버라이드하여 문자열 값이 같은지를 비교하지만,
Person 클래스는 equals()를 오버라이드하지 않았기 때문에 
Object의 equals()를 그대로 사용하여 == 와 같은 비교를 수행하게 됩니다.
*/

equals() 메서드 오버라이딩

예제

equals() 메서드를 오버라이딩하면 논리적 동등성을 비교할 수 있습니다.

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return name.equals(person.name);
    }
}

public class EqualsOverrideExample {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");

        System.out.println(p1.equals(p2)); // true (이제 논리적으로 같은 객체로 판단됨)
    }
}

equals() 오버라이딩할 때 주의할 점

  1. 반사성 R: x.equals(x) 는 항상 true 여야 합니다.

  2. 대칭성 S: x.equals(y) 가 true 이면 y.equals(x) 도 true 여야 합니다.

  3. 추이성 T: x.equals(y) 가 true 이고 y.equals(z) 가 true 이면 x.equals(z) 도 true 여야 합니다.

  4. 일관성 C: equals() 결과는 입력값이 변하지 않는 한 항상 동일해야 합니다.

  5. Null 비교: x.equals(null) 은 항상 false 를 반환해야 합니다.


hashCode()와 equals()의 관계

예제

import java.util.Objects;

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

public class HashCodeExample {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");

        System.out.println(p1.equals(p2)); // true
        System.out.println(p1.hashCode() == p2.hashCode()); // true
    }
}
  • equals() 를 오버라이드하면 hashCode() 도 함께 오버라이드해야 합니다.
  • hashCode() 값이 같으면 equals() 가 true 일 가능성이 있지만, 반대는 보장되지 않습니다.
  • HashMap, HashSet 등 해시 기반 컬렉션을 사용할 때 반드시 hashCode() 를 재정의해야 합니다.

Java에서 동일성과 동등성이 중요한 이유

  1. 컬렉션(예: HashSet, HashMap, TreeSet 등)
    equals() 와 hashCode() 를 적절히 오버라이드하지 않으면, 해시 기반 컬렉션에서 중복을 제대로 처리할 수 없습니다.

  2. 객체 비교 로직
    == 를 사용하면 의도치 않게 다른 객체로 판별될 수 있습니다. 따라서 값을 비교할 때는 equals() 를 사용해야 합니다.

  3. 객체 동작 예측 가능성
    equals() 와 hashCode() 를 잘못 오버라이드하면 버그가 발생할 가능성이 높아집니다.


== 와 equals() 의 차이를 직관적으로 본다면 ?

메모리 주소 비교 (Identity)            값 비교 (Equality)
----------------------------------------------------
Person p1 = new Person("Alice");  |  Person p1 = new Person("Alice");
Person p2 = new Person("Alice");  |  Person p2 = new Person("Alice");

p1 == p2  -> false                |  p1.equals(p2) -> true (equals 오버라이딩)
----------------------------------------------------

정리

  • Identity (==): 객체의 메모리 주소 를 비교
  • Equality (equals()): 객체의 값 을 비교
  • equals() 를 오버라이딩할 때는 hashCode() 도 같이 오버라이드해야 함
  • 해시 기반 컬렉션(HashSet, HashMap 등)에서 제대로 동작하려면 equals() 와 hashCode() 를 반드시 구현해야합니다.
profile
정진, "어제보다 더 나은 오늘이 되자"

0개의 댓글