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()vsorElse(): 지연 평가 vs 즉시 평가- 값이 항상 있어야 하거나 예외가 더 적절한 곳에는 굳이 쓰지 않는다.
참고
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.