[Java] Objects.requireNonNull이란?

이펙티브 자바를 읽다가 null에 대한 체크를 위해 Objects 클래스의 requireNonNull 을 사용하는 것을 알게 되었다. 따라서, 이에 대해 정리하고 왜 사용하는지에 대해 알아보자.


requireNonNull

requireNonNull

Java 7에 추가된 Objects 클래스에서 제공하는 Null 체크를 위한 메서드

이다.

파라미터로 입력된 값이 null이라면 NullPointerException(NPE)이 발생하고, 그렇지 않다면 입력값을 그래도 반환한다.

Java 11을 기준으로 requireNonNull 은 다음과 같이 3가지로 오버로딩 되어있다.

리턴 타입(Return Type) 메서드(Method)
T requireNonNull(T obj)
T requireNonNull(T obj, String message)
T requireNonNull(T obj, Supplier messageSupplier)

requireNonNull(T obj)

첫 번째 메서드는 null 을 전달하면 오류메시지가 비어있는 NPE를 던진다.

Objects.requireNonNull(null);
// 결과 : java.lang.NullPointerException

String normalStr = Objects.requireNonNull("일반적인 객체");
System.out.println(normalStr);
// 결과 : 일반적인 객체

requireNonNull(T obj, String message)

두 번째 메서드는 null 을 전달하면, 두 번째 파라미터로 전달된 문자열을 오류메시지로 갖는 NPE를 던진다.

Objects.requireNonNull(null, "null은 입력될 수 없습니다.");

// 결과 : java.lang.NullPointerException: null은 입력될 수 없습니다.

requireNonNull(T obj, Supplier messageSupplier)

마지막 메서드는 null 을 전달하면, 두 번째 파라미터로 전달한 Supplier를 구현한 익명 함수의 반환값을 오류메시지로 갖는 NPE를 던진다.

Objects.requireNonNull(null, () -> "null은 입력될 수 없습니다.");

// 결과 : java.lang.NullPointerException: null은 입력될 수 없습니다.

실제 구현된 코드를 확인해보면, 위와 같다.


❓사용하는 이유

위 코드의 내용을 보면 너무 당연한 내용이다. null이면 NPE를 던지고, 아니라면 그대로 반환하기 때문이다. 그렇다면 requireNonNull을 왜 사용할까?


Fail-Fast

첫 번째 이유로 Fail-Fast를 들 수 있다. Fail-Fast란, 장애가 발생한 시점에서 즉시 파악할 수 있는 것을 말한다. 디버깅을 쉽게 하기 위해서 문제가 발생한 경우 즉각적으로 감지할 필요가 있다. 문제의 원인과 발생 지점이 멀리 떨어져 있다면, 오류를 찾는데 걸리는 시간이 오래 걸릴 것이다. 즉, 시스템이 복잡해 질 수록 장애를 발견하기 어렵게 된다.


명시성

다음 두 가지 예시 코드를 보자.


수동 null 체크

String nullString = null;

if(nullString == null) {
    throw new NullPointerException("입력값이 null입니다.");
}

requireNonNull을 이용한 null 체크

String nullString = null;
Objects.requireNonNull(nullString, "입력값이 null입니다.");

위 두 코드를 확인해보면, requireNonNull을 사용한 코드가 훨씬 가독성이 좋고, 명시적인 표현 방법인 것을 알 수 있다.


참고