Objects 클래스의 equals와 deepEquals 메소드 차이.
- 소스까봤습니다
- 2019. 12. 17. 11:36
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를 도는 로직을 타게됨.