-
Enum을 비교할 때에는 ==과 equals()중 어떤 것을 써야 할까?One Cookie a day 2024. 2. 6. 10:23
회사에서 MergeRequest를 올리고 코드 리뷰를 팀원께 요청드렸었는데, 아래와 같이 Dto에 있던 enumType비교 시 ==기호를 사용한 것에 대해 코드 리뷰가 달렸었다.
if (someDto.type == someEnumType.Atype) { // do something }
Enum 비교에 있어서 equals( )와 ==의 차이에 대해 공부해보는것도 좋을 것 같다고 공부할만한 토픽을 하나 주셔서, 겸사겸사 공부한 것을 정리하려 포스팅한다.
equals( )와 == 연산의 차이는 CS 스터디때도, 멘토링 공부하면서도 알고 있던 부분이라고 생각했고, 다시 내가 공부했던 내용을 찾아보면 아래와 같다.
- equals()는 참조 변수의 값이 같은지 비교하는 메소드로, 재정의 되어있지 않다면 객체의 주소값을 비교하여 동일 객체인지 비교후 boolean 값을 리턴하는 메소드이다.
- hashCode()도 오버라이딩 해줘야 제대로 중복 객체가 Hash 자료구조에 들어오는 것을 방지할 수 있음
- == 연산자는 primitive type일 경우 값을, 그 외에는 주소값을 비교하는 연산자이다.
그래서 equals()의 경우, String 클래스에는 따로 내용물만 비교할 수 있도록 overriding 되어 있다.
하지만 Oracle Docs의 Enum class를 보면 equals() 메소드는 final로 선언이 되어있다.
즉, Enum에서의 equals 오버라이딩을 더는 허용하지 않는다는 뜻이고, equals 호출 시 Object의 equlals 호출하여 사용한다. Object의 equals는 아래와 같이 되어 있다.
public boolean equals(Object obj) { return (this == obj); }
Oracle 공식 문서에도 아래처럼 나와 있다.
https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.9
[ ... 중략 ]
Because there is only one instance of each enum constant, it is permitted to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant.
The equals method in Enum is a final method that merely invokes super.equals on its argument and returns the result, thus performing an identity comparison.- enum 상수는 1개만 존재하기 때문에, 2개의 객체를 비교할 때 ==을 사용해도 된다.
- Enum에서의 equals 메소드는 단지 super.equals를 호출하여 동일성 비교를 수행하는 메소드이다.
이를 보고, 나는 Enum 타입의 경우, == 연산과 equals의 차이가 없으며 NPE 발생 여부만 다르다고 판단하고, 추가적으로 == 과 equals 메소드를 가지고 실험도 해봤다.
public class Main { public static void main(String[] args) { Test test = new Test(Types.RED); Test test2 = new Test(Types.RED); Test test3 = new Test(); // 같은 enum 넣은 경우 equals든, ==이든 동일하게 true System.out.println(test.types.equals(test2.types)); System.out.println(test.types == test2.types); // 그냥 enum 상수 자체와 비교해도 둘다 true System.out.println(test.types.equals(Types.RED)); System.out.println(test.types == Types.RED); // test3의 types는 null, equals든, ==이든 동일하게 false System.out.println(test.types.equals(test3.types)); System.out.println(test.types == test3.types); // false System.out.println(new Test().types == Types.RED); // NPE 발생 System.out.println(new Test().types.equals(Types.RED)); } static class Test { Types types = null; Test (Types types) { this.types = types; } Test() { } } }
주목할 것은 이 부분이다.
Null 이 들어있을 때 두 연산자는 어떤 결과를 뱉는가?
// false System.out.println(new Test().types == Types.RED); // NPE 발생 System.out.println(new Test().types.equals(Types.RED));
Null값이 들어왔을 때, == 연산자는 단지 false를 반환하고, equals 메소드는 NPE를 발생 시킨다.
기초적인 것이지만 늘 헷갈리는 부분인만큼 이번 기회에 다시 정리해두었다.
팀원 분 덕분에 좋은 공부를 할 수 있었다 :DD
'One Cookie a day' 카테고리의 다른 글
Transaction에 대해서 알아보자 (0) 2023.10.27 싱글톤 디자인 패턴에 대해 (0) 2023.10.16 Java 7 이상에서 ArrayList 크기 계산 시 비트 연산자를 활용하는 이유 (0) 2023.10.10 ArrayList는 어떻게 동적으로 크기를 늘릴 수 있을까? (0) 2023.10.09 Java 5부터 등장한 Generic은 하위 버전에 어떻게 호환이 되는걸까? (0) 2023.09.30