동등성과 동일성

de_sj_awa·2021년 5월 9일
0

동등성과 동일성

두 변수의 값을 비교하기 위해 자바에서는 == 연산자를 사용한다. 하지만, 이 연산자를 이용한 비교는 primitive 타입의 자료형만 해당한다. primitive 타입의 자료형에는 byte, short, int, long, float, double, boolean이 있다.

그러나 new 연산을 통해 생성되는 reference 타입의 자료형은 ==를 사용해 값을 비교할 수 없다. new 연산자란 간단히 클래스의 오브젝트를 생성하는 연산자라고 표현할 수 있지만, 상세하게 말하면 클래스의 오브젝트를 생성하여 메모리에 올리고, 그 참조변수를 반환해주는 연산자이다. 참조변수란 메모리에 올라간 오브젝트를 가리키는 주소값이다. 이러한 reference 타입 자료형을 비교할 때는 primitive 타입 변수와는 달리 값의 비교가 두 가지 의미를 갖는다.

바로 동일성과 동등성의 개념이다.

동일하다는 두 개의 오브젝트가 완전히 같을 경우를 의미하고,
동등하다는 두 개의 오브젝트가 같은 정보를 같고 있을 경우를 의미한다.

동일하다의 경우 == 연산자로 표시되고, 동등하다의 경우 equals 연산자로 표시된다. 오브젝트 간 == 연산자는 주소값의 비교, equals는 내용의 비교가 된다.

== 연산자가 성립한다는 것은 주소값이 같다는 뜻이고, 결국 두 변수가 같은 오브젝트를 가리키고 있다는 의미가 된다.

자바에서 equals()를 따로 구현하지 않은 경우 Object 클래스의 equals()가 호출되며, Object 클래스의 equals()는 아래 코드처럼 동일성을 비교한다.

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

System.out.println(object)를 통해 확인하면 대상 오브젝트에 부여된 고유한 hashCode를 확인할 수 있다.

때문에 동등성 비교를 위해서는 구현하는 클래스에 equals 메소드를 Override해서 구현해야 한다.

하지만 String의 경우 reference 타입의 자료형임에도 불구하고 리터럴 방식("")으로 String 객체를 생성하면 == 비교를 했을 때 true가 반환된다. 리터럴 방식으로 String 객체를 생성하면 constant pool 영역에 생성된다. 이때 JVM은 객체의 heap 영역이 아니라, constant pool 영역으로 찾아간다. 그리고 constant pool 영역에 이전과 같은 값을 가지고 있는 String 객체가 있다면, 그 객체의 주소값을 반환하여 참조하도록 한다.

String 또한 객체이지만 equals가 재정의 되어 있기 때문에 리터럴 방식으로 생성하면 다음과 같은 결과가 나온다.

  public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (!COMPACT_STRINGS || this.coder == aString.coder) {
                return StringLatin1.equals(value, aString.value);
            }
        }
        return false;
    }
        String a = "a";
        String b = "a";
        
        System.out.println(a.equals(b)); 
true

참고

profile
이것저것 관심많은 개발자.

0개의 댓글