포스트

Optional

Optional

Optional이 필요한 이유

  • NullPointerException(NPE) 문제
    • 여러 메서드가 연쇄적으로 호출되어 내부에서 null 체크가 누락되면, 추적하기 어렵고 디버깅 비용이 증가
  • 가독성 저하
    • null 체크 로직이 누적되면 코드가 복잡해지고 가독성이 떨어짐
  • 의도가 드러나지 않음
    • 메서드 시그니처만 보고서는 이 메서드가 null을 반환하는지 명확히 알기 어려움

Optional 생성

메서드설명
Optional.of(T value)값이 확실히 존재 할 때
Optional.ofNullable(T value)값이 null 일 수도 있을 때, null 이면 Optional.empty()를 반환
Optional.empty()값이 없음

Optional 값 획득

메서드설명
isPresent()
isEmpty()
isPresent(): 값이 있으면 true
isEmpty(): 값이 없으면 true
get()값이 있는 경우 그 값을 반환
값이 없으면 NoSuchElementException 발생
직접 사용 시 주의
orElse, orElseXxx 계열 메서드를 사용하는 것이 안전
orElse(T other)값이 있으면 그 값을 반환
없으면 other를 반환
orElseGet(Supplier<? extends T> supplier)값이 있으면 그 값을 반환
없으면 supplier 호출하여 생성된 값을 반환
orElseThrow(…)값이 있으면 그 값을 반환
없으면 지정한 예외를 던짐
or(Supplier<? extends Optional<? extends T» supplier)값이 있으면 해당 값의 Optional 갓을 반환
값이 없으면 supplier가 제공하는 다른 Optional을 반환

Optional 값 처리

메서드설명
ifPresent(Consumer<? super T> action값이 존재하면 action 실행
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)값이 존재하면 action실행
값이 없으면 emptyAction 실행
map(Function<? super T, ? extends U> mapper)값이 있으면 mapper를 적용한 Optional 결과 반환
값이 없으면 Optional.empty() 반환
flatMap(Function<? super T, ? extends Optional<? extends U» mapper)map과 유사하지만, Optional을 평탄화 하여 반환
filter(Predicate<? super T> predicate)값이 있고 조건을 만족하면 그대로 반환
비어 있거나, 조건 불만족이면 Optional.empty() 반환
stream()값이 있으면 단일 요소를 담은 Stream 반환
값이 없으면 빈 Stream 반환
  • orElse: 즉시 평가
  • orElseGet: 지연 평가

즉, orElseGet을 사용하면 불필요한 연산을 하지 않게 되어 성능에 더 좋습니다.

베스트 프랙티스

  • 필드는 지양, 메서드 반환값에 Optional 사용
  • 메서드 파라미터로 Optional 받지 말 것
  • 컬렉션은 굳이 Optional로 감싸지 말고, 빈 컬렉션을 반환
  • isPresent() + get() 대신 다양한 메서드(orElse, orElseGet, ifPresentOrElse, map, filter…) 활용
  • orElseGet() vs orElse(): 지연 평가 vs 즉시 평가
  • 값이 항상 있어야 하거나 예외가 더 적절한 곳에는 굳이 쓰지 않는다.

참고

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.