We will find a way, we always have.

-interstellar

Programming Language/자바

[자바] ENUM에서 equals() vs ==, NPE(NullPointerException)의 고찰

Redddy 2024. 4. 3. 02:05

서론

자바는 상수를 우아하게 관리하기 위해 enum을 제공한다.

이때 enum 값들은 전부 상수로 관리되는데 이 값들을 비교할 때 equals 메서드를 사용하느냐 아니면 == 으로 비교하느냐에 대해 토론의 장이 열렸다.

스택 오버플로우에도 쏼라쏼라 말이 많은 주제인 듯 하다.

 

본론으로 가기전 짚어야 할 점은 enum의 equals 메서드는 final로 정의되어 있어 재정의가 불가하며, 안에서 ==을 사용하여 비교를 한다.

 

enum의 equals

 

본론

첫번째로 enum의 값을 비교할 때 ==를 사용할 것인가 equals를 사용할 것인가에 대한 토론을 하였다.

==을 사용했을 때 얻을 수 있는 장점은 컴파일 타임에 체크가 가능하다는 것이고, 또한 NPE(NullPointerException)을 피할 수 있다는 것이었다.

 

 

그렇게 자연스럽게 두번째 토론으로 넘어갔다.

만약 파라미터로 null 값이 들어오게 됐을 때 비교를 한다면 false를 반환하는 게 맞을 지 NPE를 떠뜨리는게 맞을지.

 

 

 

  • 1번 방식은 camp에 null이 들어오면 NPE가 터진다.
  • 2번 방식은 camp에 null이 들어와도 false를 반환한다.
  • 3번 방식은 camp에 null이 들어와도 false를 반환한다.

여기서 잠깐!! 1번 방식은 왜??? NPE가 터질까?

만약 camp가 null이라면 아래 사진과 같은 형태가 될 것이다.

 

null.equals()

null은 Object를 구현하고 있지 않아 아무런 메서드(equals 메서드)를 제공하지 않기에 예외가 발생한다.

 

 

다시 본론으로 넘어가서,,

어떤 값과 null을 비교한다는 것은 일단 null이 온 거 부터가 뭔가 잘못된 값이 들어온 것이니 예외를 던져 처리하란 메시지를 남겨야하지 않겠냐는 주장을 펼치는 크루가 있었고, 나의 의견은 파라미터로 null이 오든 뭐가 오든 equals 메서드는 "맞다 아니다"만 말하면 되지 여기서 예외를 던질 필요가 없다는 의견이였다.

 

크루의 코드를 살펴보니 Connection 객체를 처음에 null로 할당하고 커넥션 획득하는 과정에서 equals가 아닌 == 비교를 사용하고 있었다. 

만약 위의 주장대로라면 null.equals(null) 형태로 사용하여 false가 아닌 NPE를 떠뜨리는게 맞지만 null == null로 비교하여 커넥션을 할당하고 있었다. 그렇게 enum 비교는 equals 대신 ==을 사용하는 방향으로 가는데 성공했다.

 

추가로 이런 의문도 들었다.

 

A는 B와 다르다. 그러면 B와 A도 다르다가 성립해야하는데, B가 만약 null이라면 B와 A는 같니?라고 물어보는 순간 뻥 🎉✨하고 NPE가 터진다.

 

Objects.equals() 메서드도 아래처럼 구현되어 있다.

 

 

Enum을 사용한다면 == 을 사용하여 NPE 방지가 가능하지만, 객체를 비교한다면 위와 같은 상황이 발생한다.

상수.equals(파라미터)파라미터.equals(상수)의 결과가 하나는 false를 반환하는데 하나는 예외를 던질 수 있다는 것이다.

 

이게 맞을까? 자바 언어 이대로 괜찮은가?