목차

Java Optional 개념 및 사용법

개발을 하다 보면 NullPointException(NPE)을 만나게 된다. 가장 많이 발생하는 에러 중 하나라고 하는데, 이를 피하기 위해선 null을 체크하는 로직이 추가되어야 한다.

DeviceVo deviceVo = deviceDao.findById(deviceId);
deviceVo.getName(); // deviceVo가 null이면 NullPointException 발생

if(deviceVo != null){
	deviceVo.getName();
	if(deviceVo.getModel() != null) {
		deviceVo.getModel().getModelId();
	}
}

null 체크해야 될 부분이 많다면 코드가 복잡해져 가독성이 떨어지는 단점이 있다.

Java 8에서는 Optional<T> 클래스를 도입하였는데, null이 될 수도 있는 객체를 감싸고 있는 Wrapper 클래스이다. Optional로 객체를 감싸서 사용하게 되면 NPE 방지를 위해 null 체크를 직접 하지 않아도 된다.

빈 Optional 객체는 아래와 같이 생성 할 수 있다.

Optional<String> optional = Optional.empty();

System.out.println(optional); // Optional.empty
System.out.println(optional.isPresent()); // false

of() 메서드는 value가 null인 경우 NPE를 발생시킨다. 반드시 값이 있는 경우에만 사용할 것.

Optional<String> optional = Optional.of(value);

ofNullable() 메서드는 value가 null일 경우 NPE 대신 Optional.empty를 반환한다.

Optional<String> optional = Optional.ofNullable(value);
System.out.println(optional); // Optional.empty
  • filter() : 람다식이 true면 Optional 객체를 그대로, false이면 Optional.empty()를 리턴한다.
String result1 = Optional.of("ABCDE")
                        .filter((val) -> val.contains("ABC"))
                        .orElse("Does not contain ABC");
System.out.println(result1); //ABCDE

String result2 = Optional.of("CDEFG")
                        .filter((val) -> val.contains("ABC"))
                        .orElse("Does not contain ABC");
System.out.println(result2); //Does not contain ABC
  • map() : 입력값을 다른값으로 변환하는 메서드
String result3 = Optional.of("abcde")
                        .map(String::toUpperCase)
                        .orElse("fail");
System.out.println(result3); //ABCDE
  • isPresent() : 값의 유무에 따라 true, false 반환
  • ifPresent() : 람다식을 인자로 받아 값이 있을때만 람다식이 실행됨
Optional.of("ABCDE")
    .ifPresent(System.out::println); // ABCDE

Optional.ofNullable(null)
    .ifPresent(System.out::println); // 아무것도 출력되지 않음
  • get() : Optional 객체의 value를 가져온다. 값이 없으면 NoSuchElementException 발생
  • orElse() : Optional 객체가 비었다면 실행된다.
String result2 = Optional.of("CDEFG")
                        .filter((val) -> val.contains("ABC"))
                        .orElse("Does not contain ABC");
System.out.println(result2); //Does not contain ABC
  • orElseGet() : Optional 객체가 비었다면 기본값으로 제공할 supplier를 지정한다. orElse()는 null 여부와 상관없이 항상 호출되며, orElseGet()은 null일때만 호출된다.
  • orElseThrow() : Optional 객체가 비어있다면 예외를 발생시킨다.
String result1 = Optional.of("CDEFG")
                        .filter((val) -> val.contains("ABC"))
                        .orElseThrow(NoSuchElementException::new);