프로젝트/Kidsping

개발 기록 - Java에서 Enum 의 비교는 '==' 인가? 'equals' 인가?

an_jjin 2024. 10. 22. 21:47

Overview

public void updateMbtiScore(BookMBTI bookMBTI, LikeMbti like) {
    int multiplier = (like.getLikeStatus() == LikeStatus.DISLIKE) ? 2 : 1;
    this.eScore += multiplier * bookMBTI.getEScore();
    this.iScore += multiplier * bookMBTI.getIScore();
    this.sScore += multiplier * bookMBTI.getSScore();
    this.nScore += multiplier * bookMBTI.getNScore();
    this.tScore += multiplier * bookMBTI.getTScore();
    this.fScore += multiplier * bookMBTI.getFScore();
    this.jScore += multiplier * bookMBTI.getJScore();
    this.pScore += multiplier * bookMBTI.getPScore();
}

like.getLikeStatus() == LikeStatus.DISLIKE 부분은 enum끼리의 비교입니다.

이렇게 enum을 비교하는 로직을 짜면서 equals를 쓰면 좋을지 == 를 쓰면 좋을지에 대한 의문이 생겼습니다.

그래서 이번 글에서는 Enum의 비교에 대해 정리하려 합니다.

Enum 값을 비교하기(== vs equals)

Java에서 Enum 은 클래스 인스턴스가 JVM 내에 하나만 존재하도록 100% 보장되는 싱글톤 객체입니다.(JLS, 8.9 Enum Types) 그렇다면 Enum 비교 시 equals 메서드 대신 간단히 == 비교를 사용하면 어떨까요?

 

간단하게 테스트 코드를 통해서 확인해 보겠습니다.

public class EnumTest {

    @Test
    void enumTest() {
        Mbti mbti = Mbti.ISFJ;

        assertThat(mbti == Mbti.ISFJ).isTrue();
        assertThat(mbti.equals(Mbti.ISFJ)).isTrue();

        assertThat(Mbti.ISFJ == mbti).isTrue();
        assertThat(Mbti.ISFJ.equals(mbti)).isTrue();
    }

    public enum Mbti {
        ISTP,
        ISFJ
    }
}

테스트를 수행해 보면 모두 통과하는 것을 확인할 수 있는데, 이는 equals 메서드를 확인해 보면 알 수 있습니다.

아래 그림에서와 같이 equals 메서드도 결국 == 연산자를 통해서 비교하고 있는 것을 확인할 수 있습니다.

1. == 비교는 NullPointerException을 발생시키지 않습니다.

public class EnumTest {

    @Test
    void enumTest() {
        Mbti mbti = null;

        System.out.println(mbti == Mbti.ISFJ);
        System.out.println(mbti.equals(Mbti.ISFJ)); // NPE 발생

        System.out.println(Mbti.ISFJ == mbti);
        System.out.println(Mbti.ISFJ.equals(mbti));
    }

    public enum Mbti {
        ISTP,
        ISFJ
    }
}

== 비교는 NPE(NullPointerException)을 발생시키지 않습니다.

eqauls 메서드를 사용하여 비교하면 Runtime(런타임)에 NPE가 발생할 수 있습니다.

(But, equals 메서드에서도 Enum을 먼저 앞에 두고 비교하면 NPE에서 벗어날 수 있습니다.)

위에 설명에서와 같이 NPE를 방지하는 것뿐만 아니라 상수값, Enum과 같은 변하지 않는 값들을 앞에 작성해서 비교하는 것이 좋습니다.

2. == 비교는 컴파일 타임에 타입 호환성 검사를 지원합니다.

위의 그림에서 확인하실 수 있듯이, == 비교를 사용하면 실수로 잘못된 타입 비교를 작성하여도 컴파일 과정에서 확인이 되지만 equals 메서드를 사용하게 되면 그대로 컴파일이 되어 버립니다. 즉 == 비교를 사용하면 프로그래머가 실수로 잘못된 타입 비교를 작성해도 컴파일 타임에 검사 되지만 equals 메서드를 사용하면 그대로 컴파일이 되어 버립니다.

마무리

== 비교가 코드도 간결해지고 직관적이기 때문에 정답이라고 생각했습니다.

하지만 반대의 생각을 가지신 분들도 많은 주제인 것 같습니다.

(참고: stackoverflow/comparing-java-enum-members-or-equals)

그래서 이 문제는 정답이 딱 정해져 있는 문제는 아니라고 생각하지만 컴파일 단계에서 실수를 확인할 수 있는 == 비교가 조금 더 유용하지 않을까라는 생각을 가지게 되었습니다.

참고

https://castlejune.tistory.com/34

https://dev-jwblog.tistory.com/169