본문 바로가기
👨‍🏫Study/JAVA

[JAVA] NullPointerException 처리방법

by 코푸는 개발자 2022. 3. 30.
728x90

1. NullPointerException

NullPointerException은 실제 값이 아닌 null을 가지고 있는 객체/변수를 호출할 때 발생하는 예외이다.

String str = null;
System.out.println(str.toString());

*이럴 때 예외가 발생하는게 null에는 toString이 없기 때문이다. 문제는 프로그래밍을 하다보면 해당 변수에 null이 들어있는지, 아닌지를 구분하기가 어렵다는 점이다. 그래서 NullPointerException 처리 방법으로 크게 세 가지가 있다.

*일반적으로 NPE(NullPointerException)로 표시한다.

2. 처리방법

2.1. Try-Catch

String s = null;
  
try {
    s = s.toUpperCase(); //s를 대문자로 바꾸면서 NullPointerException 발생
    System.out.println(s); //실행되지 않는다.
} catch(NullPointerException e){
    s = "empty";
    System.out.println(s.toUpperCase()); //catch문에서 대문자로 바꾸어준다.
}finally{
    System.out.println("무조건 실행됩니다.");
}

 

*이렇게 한다면 변수를 사용할 때마다 try-catch를 섞으면 코드의 양이 너무 많아질 수 있다.

 

 

2.2. if (variable !=  null)

public String getCityOfMemberFromOrder(Order order) {
    if (order != null) {
        Member member = order.getMember();
        if (member != null) {
            Address address = member.getAddress();
            if (address != null) {
                String city = address.getCity();
                if (city != null) {
                    return city;
                }
            }
        }
    }
    return "Seoul"; // default
}

*객체 안의 객체가 있는 구조에서는 좋지 않은 상황에 직면 할 수 있다.

 

2.3. Optional

java.util.Optional은 JDK1.8부터 추가되었다.
Optional<T\>은 지네릭 클래스로 'T타입의 객체'를 감싸는 래퍼 클래스이다.
그래서 Optional타입의 객체는 모든 타입의 참조변수를 담을 수 있다.

public final class Optional<T> {
    private final T value; // T타입의 참조변수
        ...
}

최종 연산의 결과를 그냥 반환하는게 아니라 Optional 객체에 담아서 반환하는 것이다. 이처럼 객체에 담아서 반환을 하면, 반환된 결과가 null인지 매번 if문으로 체크하는 대신 Optional에 정의된 메서드를 통해서 간단히 처리할 수 있다.
이제 널 체크를 위한 if문 없이도 NullPointerException이 발생하지 않는 코드 작성이 가능하다.

 

Optional에서 얻는 장점

  • NPE를 유발할 수 있는 null을 직접 다루지 않아도 된다
  • 수고롭게 null 체크를 직접 하지 않아도 된다
  • 명시적으로 해당 변수가 null일 수도 있다는 가능성을 표현할 수 있다. (따라서 불필요한 방어 로직을 줄일 수 있다.)

 

Optional 기본 사용법
Optional 의 static method 인 empty(), of(), ofNullable() 을 통해서만 Optional 객체를 생성할 수 있다.

참조변수의 값이 null일 가능성이 있으면, of() 대신 ofNullable()을 사용해야한다. of()는 매개변수의 값이 null이면 NullPointerException이 발생하기 때문이다.

Optional<String> optVal = Optional.of(null); //NPE 발생
Optional<String> optVal = Optional.ofNullable(null); // OK

Optional<T>타입의 참조변수를 기본값으로 초기화할 때는 empty()를 사용한다. null로 초기화하는 것도 가능하지만, empty()로 초기화하는 것이 바람직하다.

Optional<String> optVal = null ;
Optional<String> optVal = Optional.<String>empty(); // 빈 객체로 초기화

 

Optional 객체의 값 가져오기

 

Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get(); //optVal에 저장된 값을 반환. null이면 예외 발생
String str2 = optVal.orElse(""); //optVal에 저장된 값이 null일 때는 ""를 반환

만약 Optional 없이 쓰면 코드를 아래와 같이 쓸 것이다.

SoundCard soundcard = ...;
if(soundcard != null){
  System.out.println(soundcard);
}

Optional을 쓰면 아래와 같이 수정할 수 있다.

Optional<Soundcard> soundcard = ...;
soundcard.ifPresent(System.out::println);

하지만 그렇다면 null check를 할 때

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

이렇게되는데 기존의 if와 크게 차이가 나지 않아 보인다.

Optional<Soundcard> maybeSoundcard = Optional.ofNullable(someSoundcard);
Soundcard soundcard = maybeSoundcard.orElse(new Soundcard("default"));

 

 

728x90

댓글