Java에서 문자열을 다룰 때 자주 마주치는 예외 중 하나가 바로 NullPointerException(NPE)입니다.
그중에서도 null.isEmpty() 같은 코드는 개발을 처음 시작할 때 흔히 접하게 되는 에러입니다.

처음에는 "null이면 비어 있는 거 아닌가? 그럼 isEmpty() 써도 되지 않나?" 라고 생각할 수 있지만, 사실 null과 ""(빈 문자열)는 엄연히 다른 개념입니다.

이 글에서는 null.isEmpty()가 왜 예외를 발생시키는지 그 이유를 알아보고, 이를 방지하기 위한 안전한 코딩 패턴을 소개해드리겠습니다.






[문제 상황]

String str = null;

if (str.isEmpty()) {
    System.out.println("비어 있습니다!");
}

 

위 코드는 실행 시 다음과 같은 예외를 발생시킵니다.

Exception in thread "main" java.lang.NullPointerException

 

[ 왜? why? ]

먼저, String은 클래스이며, 실제로는 객체(즉, 참조값)를 다루게 됩니다. 그리고 isEmpty()는 String 클래스의 인스턴스 메서드입니다.

즉, 이 메서드를 호출하려면 반드시 String 객체가 생성되어 있어야 합니다.

하지만 앞선 예제에서 str은 null이기 때문에, 존재하지 않는 참조(= 아무것도 가리키지 않는 상태)에서 메서드를 호출하려고 시도하게 되고, 이로 인해 NullPointerException이 발생하는 것입니다.

 

 

[ 안전한 코드 작성 방법 ]

이런 경우에는 null 여부를 먼저 확인하면 좋습니다.

if (str != null && !str.isEmpty()) {
    System.out.println("비어있지 않은 문자열입니다.");
}

 

<주의>

어라? 가만히 생각해보면 isEmpty()를 먼저 확인하고 나중에 null 체크해도 괜찮은 거 아닌가?
저도 한순간 그렇게 생각했던 적이 있었습니다.

하지만 이렇게 작성하면 NPE가 그대로 발생합니다.
왜냐하면 str이 null인 상태에서 isEmpty()를 먼저 호출하게 되기 때문이죠.

Java의 논리 연산자(&&, ||)는 단축 평가를 사용합니다.
즉, 왼쪽 조건이 false일 경우 오른쪽 조건은 아예 실행되지 않기 때문에, 조건의 순서가 매우 중요합니다!

그래서 위 예제에서 str != null이 false라면 str.isEmpty()는 실행되지 않기 때문에 NPE가 발생하지 않습니다.

 

[ 추가 안전한 코드 작성 방법 ]

Java 11 이상에서는 isBlank()를 사용하면 공백 문자열까지 함께 처리할 수 있습니다.

if (str != null && !str.isBlank()) {
    // 공백이 아닌 문자열 처리
}

 

또는 Objects.toString(str, "")를 활용하여 null을 빈 문자열로 대체할 수도 있습니다.

if (!Objects.toString(str, "").isEmpty()) {
    // null도 안전하게 처리
}

 

[ 정리 ]

1. String은 클래스

2. isEmpty()는 String 클래스의 인스턴스 메서드

3. 반드시 String 객체가 생성되어 있어야한다

4. null은 존재하지 않는 참조

5. 이로 인해 NPE 발생

+ Recent posts