Notice
Recent Posts
Recent Comments
Link
관리 메뉴

look-forest

Optional 본문

Java/모던 자바(Java 8+)

Optional

studyHub 2024. 11. 9. 21:41

Optional 소개

Optional : 오직 값 한 개가 들어있을 수도 없을 수도 있는 컨네이너.

객체 Null 체크를 잊을 수 있기도 하고, 번거롭기도 해서 편의상 등장했다.

Optional은 클라이언트에 코드에게 명시적으로 빈 값일 수도 있다는 걸 알려주고, 빈 값인 경우에 대한 처리를 강제한다.

 

메소드에서 작업 중 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택할 수 있는 방법

  • 예외를 던진다. (비싸다, 스택트레이스를 찍어두니까.)
  • null을 리턴한다. (비용 문제가 없지만 그 코드를 사용하는 클라이언트 코드가 주의해야 한다.)
  • Optional을 리턴한다.

 

주의할 것

  • 리턴값으로만 쓰자. 메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말자.
    (매개변수, 필드 등에 null이 들어갈 수 있는데, null.ifPresent()를 사용하면 NPE 발생.. 의미가 없어진다.)

  • Optional을 리턴하는 메소드에서 null을 리턴하지 말자. Optional.empty()로 리턴해라.
    (Optional을 사용하는 의미가 없다. null.ifPresent()를 사용하면 NPE 발생..)

  • Optional로 감쌀 객체가 Null일 수 있으면 ofNullable()을 사용하자.

  • 프리미티브 타입용 Optional을 따로 있다. OptionalInt, OptionalLong,...
    Optional.of(10)으로 만들면 boxing, unboxing이 일어나서 성능에 좋지 않다.

  • Collection, Map, Stream Array, Optional은 Opiontal로 감싸지 말 것.
    이미 빈값인지 확인할 수 있는 컨테이너다. Optional로 두번 감쌀 이유가 없다.
public Optional<Progress> getProgress() {
    return Optional.ofNullable(progress); //ofNullable : null일 수 있다. of로 만들면 null일 경우 NPE
}

 


 

Optional API

Optional 만들기

  • Optional.of()  -> 감쌀 객체가 null이면 NPE 발생
  • Optional.ofNullable()
  • Optional.empty()

 

Optional에 값이 있는지 없는지 확인하기

  • Boolean  isPresent()
  • Boolean  isEmpty() (Java 11부터 제공)

 

Optional에 있는 값 가져오기

  • get()   -> 만약 비어있는 Optional일 경우 NoSuchElementException 발생
    => 가급적 get을 쓰지말고 아래 API를 사용해라.

 

Optional에 값이 있는 경우에 do something

  • ifPresent(Consumer)
optional.ifPresent(obj -> System.out.println(obj.getId()));

 

 

Optional에 값이 있으면 가져오고 없는 경우에

  1. T를 리턴 : orElse(T)
  2. do something : orElseGet(Supplier)
  3. 에러 발생 : orElseThrow(Supplier)
//JPA로 시작하는 수업이 없다면 비어있는 수업을 리턴하라.
OnlineClass onlineClassNull = optional.orElse(null); //여기서 객체 반환 선언하면, 값이 있는 경우도 실행. lazy하게 처리 불가.

//JPA로 시작하는 수업이 없다면 새로 만들어서 리턴하라.
OnlineClass onlineClassNew = optional.orElseGet(() -> new OnlineClass(6, "jpa", true)); //실행x. supplier는 lazy.

//JPA로 시작하는 수업이 없다면 에러를 던져라
OnlineClass onlineClassThrow = optional.orElseThrow(NoSuchElementException::new);

 

Optional에 들어있는 값 걸러내기

  • Optional filter(Predicate)
Optional<OnlineClass> onlineClass = optional.filter(oc -> oc.getId() > 10);

 

 

Optional에 들어있는 값 변환하기

  • Optional map(Function)
  • Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional인 경우에 사용하면 편리하다.
//mapping 한 값도 Optional로 반환
Optional<Integer> optionalId = optional.map(OnlineClass::getId);

//map한 것이 Optional 타입이라면, Optional이 두번 감싸진다.
Optional<Optional<Progress>> progressOptional2 = optional.map(OnlineClass::getProgress);

//이럴 때 flatMap을 쓰면 Optional을 한번만 써준다.
Optional<Progress> progressOptionalFlat = optional.flatMap(OnlineClass::getProgress);

 

 

 

 


참고 자료 & 이미지 출처
더 자바, Java 8 (백기선 님)

 

'Java > 모던 자바(Java 8+)' 카테고리의 다른 글

CompletableFuture  (0) 2024.11.09
Date와 Time  (0) 2024.11.09
Stream  (0) 2024.11.09
인터페이스의 변화  (0) 2024.11.08
함수형 인터페이스와 람다  (2) 2024.11.07