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

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개의 댓글