ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - 동일성(identity) & 동등성(equality)
    Language/Java 2022. 3. 3. 16:47

    동일성(identity) & 동등성(equality)

    동일성이란?

    동일성은 동일하다는 뜻으로 두 개의 객체가 완전히 같은 경우를 의미한다. 여기서 완전히 같다는 뜻은 두 객체가 사실상 하나의 객체로 봐도 무방하며, 주소 값이 같기 때문에 두 변수가 같은 객체를 가리키게 된다.

     

     

    위 사진에서 refVar1은 객체1을 가리키고 있고, refVar2와 refVar3는 객체2를 가리키고 있다. refVar2와 refVar3는 동일한 객체를 가리키고 있으므로, 두 변수는 동일하다고 이야기할 수 있다. 그리고 해당 변수가 동일한지 "==" 연산자를 통해 판별할 수 있다.

    추가적으로, Primitive Type은 객체가 아니라 주소가 없으므로 "==" 연산자를 사용하였을 때 내용이 같으면 동일하다고 말한다.

     

    동등성이란?

    동등성은 동등하다는 뜻으로 두 개의 객체가 같은 정보를 가지고 있는 경우를 의미한다. 동등성은 변수가 참조하고 있는 객체의 주소가 서로 다르더라도 내용만 같으면 두 변수는 동등하다고 말할 수 있다.

    동일하면 동등하지만, 동등하다고 동일한 것은 아니다. 그리고 해당 변수가 동등한 지 "equals()" 연산자를 통해 판별할 수 있다.

     

    String string01 = new String("java");
    String string02 = new String("java");
    
    System.out.println(string01 == string02);   // "false" 출력
    System.out.println(string01.equals(string02));   // "true" 출력

    new 키워드를 통해 다른 String 객체를 메모리에 할당하였으므로 string01과 string02가 가리키는 객체의 주소 값은 다르므로 동일하지 않다. 하지만 String이 재정의한 "equals()" 연산자에 의해 두 객체의 내용이 같으므로 동등하다고 할 수 있다.


    equals 연산자

    equals 연산자

    어떠한 객체든 "equals()" 연산자만 사용하면 두 객체에 대한 동등성 판단이 가능한 것은 아니다. 우선 해당 연산자가 최초로 정의된 형태를 알아보도록 하자.

     

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

    위 메서드는 모든 객체의 조상인 Object 객체에서 정의하고 있는 "equals()" 메서드이다. 반환 형태를 보면 알 수 있듯이, 단순히 동일성 비교를 하고 있다. 즉, 해당 메서드를 자식 객체에서 재정의하지 않는 이상 "equals()" 연산자는 "==" 연산자와는 다르지 않다는 것을 의미한다. 아래 예제를 통해 "equals()" 메서드를 재정의한 객체 몇 가지를 살펴보겠다.

     

    String의 equals 연산자
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

    String 클래스는 위 코드와 같이 "equals()" 메서드를 재정의하여 인자로 전달된 String의 문자열을 비교하고 있다.

    코드를 보면 "==" 연산자를 통해 두 객체의 동일성 여부를 판단하고, 두 객체가 동일하지 않다면 String인지 여부를 판단한 뒤, 문자 하나하나가 같은지를 비교한다. 만약 모든 문자가 같다면 두 객체의 내용이 같은 것이므로 동등하다고 판별할 수 있다.

     

    Integer의 equals 연산자
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

    Integer 클래스는 위와 같이 "equals()" 메서드를 재정의하여 인자로 전달된 Integer의 값을 비교하고 있다. 코드를 보면 먼저 인자로 넘어온 값이 Integer인지 확인하고, 내용에 해당하는 정수를 "==" 키워드를 통해 같은지 판단하고 있다. 만약 정수가 같다면 두 객체의 내용이 같은 것이므로 동등하다고 판별할 수 있다.

     

    Objects의 equals 연산자
    public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

    Objects 클래스는 위와 같이 "equals()" 메서드를 재정의하여 두 객체가 동등한 지 비교하는 기능을 수행하고 있다. "==" 연산자를 통해 두 객체가 동일하다면 동등하므로 true를 반환하고, 그렇지 않다면 첫 번째 매개 변수로 들어온 객체의 "equals()" 메서드를 호출하여 동등성을 판단한다. 해당 메서드는 전적으로 첫 번째 매개 변수로 들어온 객체에 의존하는 것을 알 수 있다. 만약 첫 번째 매개 변수로 들어온 객체가 "equals()" 메서드를 재정의하지 않았다면 동일성 비교를 하게 될 것이다. 즉, 개발자가 커스텀 객체를 만들었을 때, 해당 객체의 동등성 비교가 필요하다면 반드시 "equals()" 메서드를 재정의해 주어야 한다.

     

    ArrayList의 equals 연산자
    private boolean equalsArrayList(ArrayList<?> other) {
        final int otherModCount - other.modCount;
        final int s = size;
        boolean equal;
        if (equal = (s == other.size)) {
            final Object[] otherEs = other.elementData;
            final Object[] es = elementData;
            if (s > es.length || s > otherEs.length) {
                throw new ConcurrentModificationException();
            }
            for (int i = 0; i < s; i++) {
                if (!Objects.equals(es[i], otherEs[i])) {
                    equal = false;
                    break;
                }
            }
        }
        other.checkForComodification(otherModCount);
        return equal;
    }

     코드는 더 복잡하지만 핵심이 되는 부분만 살펴보겠다. 흐름을 보면, 자신의 element(객체의 내용)와 매개 변수로 들어온 ArrayList의 element(객체의 내용)가 서로 같은지 비교하고 있다. 그리고 중간에 두 element가 같은지 판단하기 위해 Objects.equals() 메서드를 사용하고 있다. 즉, ArrayList의 "equals()" 메서드는 서로의 요소 하나하나에 대해 동등성 비교를 수행하여 모든 요소가 동등하면 두 ArrayList는 동등하다고 판별한다.


    출처

    https://joont.tistory.com/143

    https://codechacha.com/ko/java-string-compare/

    [Java] 동일성(identity)과 동등성(equality) (tistory.com)

     

    728x90

    'Language > Java' 카테고리의 다른 글

    Java - 직렬화(Serialization)와 역직렬화(Deserialization)  (0) 2022.03.21
    Java - static  (0) 2022.03.04
    Java - Call by Value & Call By Reference  (0) 2022.02.21
    Java - 캐스팅(Casting)  (0) 2022.02.19
    Java - 문자열 클래스  (0) 2022.02.19

    댓글

Designed by Tistory.