Objects 클래스의 equals와 deepEquals 메소드 차이.

Objects 클래스의 equals와 deepEquals 메소드 차이.

deepEquals 메소드
public static boolean deepEquals(Object a, Object b) {
    if (a == b)
        return true;
    else if (a == null || b == null)
        return false;
    else
        return Arrays.deepEquals0(a, b);
}

- 이렇게 소스코드가 이루어져 있음. equals보다 deeply 비교를 하는 메소드

- 둘중 하나가 null 인경우는 당연히 false, 둘다 Null 인경우는 완전히 같다고 보고 true

- 나머지는 Arrays 클래스의 deepEquals0 메소드를 이용하게 되는데.

 

Arrays 클래스의 deepEquals0 메소드는 다음과 같음.

static boolean deepEquals0(Object e1, Object e2) {
    assert e1 != null;
    boolean eq;
    
    if (e1 instanceof Object[] && e2 instanceof Object[])
        eq = deepEquals ((Object[]) e1, (Object[]) e2);
    else if (e1 instanceof byte[] && e2 instanceof byte[])
        eq = equals((byte[]) e1, (byte[]) e2);
    else if (e1 instanceof short[] && e2 instanceof short[])
        eq = equals((short[]) e1, (short[]) e2);
    else if (e1 instanceof int[] && e2 instanceof int[])
        eq = equals((int[]) e1, (int[]) e2);
    else if (e1 instanceof long[] && e2 instanceof long[])
        eq = equals((long[]) e1, (long[]) e2);
    else if (e1 instanceof char[] && e2 instanceof char[])
        eq = equals((char[]) e1, (char[]) e2);
    else if (e1 instanceof float[] && e2 instanceof float[])
        eq = equals((float[]) e1, (float[]) e2);
    else if (e1 instanceof double[] && e2 instanceof double[])
        eq = equals((double[]) e1, (double[]) e2);
    else if (e1 instanceof boolean[] && e2 instanceof boolean[])
        eq = equals((boolean[]) e1, (boolean[]) e2);
    else
        eq = e1.equals(e2);
    return eq;
}

 

- assert 키워드는 단언 키워드로써 다음에 나오는 표현식(boolean 형태)이 참이 나오지 않으면 AssertionError를 뱉어낸다. JDK 1.4 이후부터 추가된 기능으로 클래스파일을 실행할 때! “Java -ea 클래스명” 과 같이 특수한 옵션을 추가해야 발동하며 그렇지 않은 경우는 실행에서 제외되는 키워드이다. IDE를 이용하는 경우 run configuration에서 옵션을 줄 수 있다. 자세한 내용은 따로 다루지는 않겠다.

 

- 어쨌든. 첫번째 인자가 null이 아니라는 단언을 받게 되고 소스를 실행합니다. 원래 Arrays 클래스 소속 메소드이지만 다른 Java 기본 api에서도 사용되는 로직이기 주로 primitive 배열타입이 필터되고 그 외의 참조형들은 Object 클래스의 equlas()를 타서 비교하게 된다. 결국 주요 로직은 맨앞의 파라미터가 NULL이 아니고 두번째 파라미터를 equlas 메소드의 인자로 넣었을 때 true가 나오면 deepEquals는 True가 된다. 즉, 두 파라미터의 값이 같다는 것이다.

 

Objects 클래스의 equals 메소드
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

- 두 인자의 주소값이 같으면 True

- a는 무조건 not null이 이어야하며 equals 메소드의 인자로 b를 넣었을 때 true가 나와야함.

(a 객체에서 사용한 equals 메소드는 우리가 흔히 알고있는 equals 메소드)

 

왠지 어디서 많이 본 로직같다….

 

바로 deepEquals의 배열이 아닐때의 로직과 같다. 

 

즉. 내가 파악해본 바로는 배열이 아닌 참조타입의 deepEquals() 메소드나 그냥 equals() 메소드나 결국 최종적으로 도달하는 로직은 똑같다는 것이다.

 

다만 "배열"에서의 값 비교 필요성은 deepEquals() 메소드에서 더욱 느껴진다.

 

equals() 메소드는 배열 내부의 요소에 대한 비교는 할 수가 없다. 그래서 모든 것(길이 결과는 다음과 같다.

Integer[] a1 = {1,2,3,4,5};
Integer[] a2 = {1,2,3,4,5};

System.out.println(a1==a2); //false
System.out.println(a1.equals(a2)); //false
System.out.println(Arrays.deepEquals(a1,a2)); //true

 

하지만 Arrays 클래스의 deepEquals 메소드는 두 배열의 내부를 탐색하기 때문에 배열 내부 비교도 가능하게 되는 것이다. 바로 이 deepEquals 메소드가 Objects 메소드에서 그대로 사용되는 것이다.

 

그래서 간단히 비교하면 equals 메소드는 배열의 요소에 대한 값비교는 할 수 없고,

deepEquals 메소드는 배열의 요소를 모두 loop를 돌아가며 비교하여 값을 반환해주는 메소드이다.

 

요약

- Objects  클래스에 equals 메소드와 deepEquals 메소드가 있음.

- 배열이 아닌 참조형인 경우, Objects 클래스의 equals 메소드와 deepEquals는 단순 값비교로 로직이 같음.

- 배열인 경우에 차이가 생김.

- eqauls 메소드는 단순 배열의 참조값비교, deepEquals메소드는 요소가 배열인 경우 loop를 도는 로직을 타게됨.

댓글

Designed by JB FACTORY