Java

[Java] Identity와 Equality

최블랙 2022. 1. 3. 18:03

동일성(Identity)와 동등성(Equality)

이전 포스팅에서 원시 타입과 참조 타입에 대해 알아보았다. 참조 타입의 객체를 비교할 때는 원시 타입 변수와 달리 값의 비교가 동일성, 동등성 두 가지의 의미를 가지게 된다.

동일성(Identity) 비교참조값을 비교하기 때문에 속성과 타입이 같아도 참조값이 다르면 다른 객체로 구분한다.

동등성(Equality) 비교는 equals 함수를 통해 객체의 속성을 비교한다.

 

하지만 객체의 최상위 클래스인 Object 클래스의 equals 함수를 보면 다음과 같이 파라미터로 받은 인스턴스와 메서드를 호출한 인스턴스 간의 동일성 비교(==)를 한다.

public boolean equals(Object obj) {
    return (this == obj);
}

다음과 같이 이름과 나이를 갖는 Person 객체가 있다고 가정해보고 확인해보면 동일성 비교(==)와 동등성(equals) 비교 둘 다 동일한 결과가 나온다.

public class Person {

    String name;
    int age;

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

    public static void main(String[] args) {
        Person person1 = new Person("홍길동", 25);
        Person person2 = new Person("홍길동", 25);
        Person person3 = person2;

        // 두 인스턴스의 참조값이 다르기 때문에 false
        System.out.println(person1 == person2);
        // 두 인스턴스의 참조값이 같기 때문에 true
        System.out.println(person2 == person3);

		System.out.println(person1.equals(person2)); // false
        System.out.println(person2.equals(person3)); // true
    }
}

동등성을 비교하기 위해서는 어떻게 해야 할까 ❔

equals 함수를 재정의함으로써 속성과 타입이 같을 때 같은 객체로 비교될 수 있도록 할 수 있다.

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age &&
            Objects.equals(name, person.name);
}
public static void main(String[] args) {
    Person person1 = new Person("홍길동", 25);
    Person person2 = new Person("홍길동", 25);
    Person person3 = person2;

    // 두 인스턴스의 참조값이 다르기 때문에 false
    System.out.println(person1 == person2);
    // 두 인스턴스의 참조값이 같기 때문에 true
    System.out.println(person2 == person3); 
    
    // 두 인스턴스의 속성이 모두 같기 때문에 true
    System.out.println(person1.equals(person2)); 
    // 두 인스턴스의 참조값이 같기 때문에 true
    System.out.println(person2.equals(person3)); 
}

String의 경우 조금 다르다

 String은 자바에서 조금 특별한 대우를 해주고 있다. String은 참조 타입이기 때문에 다른 참조 타입과 마찬가지로 new 연산자를 사용해 인스턴스를 생성하지만, 다른 방식의 초기화 방법이 있다.

String str = "홍길동";

이렇게 원시 타입 변수를 선언하듯이 String 변수를 선언할 수 있게 문법적으로 허락하고 있다. 이와 더불어 같은 문자열을 가지는 두 인스턴스의 동등성 비교(==) 결과는 true이다!!!! (new 키워드를 사용할 경우 false)

String str1 = "홍길동";
String str2 = "홍길동";
System.out.println(str1 == str2); // true

String 객체를 new 키워드를 사용하여 생성할 경우 데이터는 힙 영역에 저장되지만,
String 객체를 리터럴("")을 이용해서 생성할 경우 힙 영역이 아닌 string constant pool 영역에 저장된다. 이때 해당 문자열과 같은 값을 가지고 있는 String 객체가 있다면, 그 객체의 주소값을 반환하여 참조하도록 한다.


Reference

https://velog.io/@kyukim/VO

 

동일성과 동등성 Value Object

객체가 가지고 있는 속성과 타입이 같다면 동일한 객체로 비교하고 싶다.예를 들어서, 지난 체스 만드는 미션에서 체스말에서 체스말들을 그런식으로 비교하고 싶을 수 있다동일성(==) 비교는

velog.io

https://joont.tistory.com/143

 

동일성, 동등성

두 변수의 값을 비교하기 위해, 우리는 == 연산자를 사용했습니다. 하지만 이 연산자를 이용한 비교는, primitive(원시) 타입의 자료형에만 해당하는 사항입니다. ( primitive 타입 자료형이란 int, doubl

joont.tistory.com