Home Optional
Post
Cancel

Optional

Optional


Optional는 “존재할 수도 있지만 안 할 수도 있는 객체”, 즉, “null이 될 수도 있는 객체”을 감싸고 있는 일종의 래퍼 클래스입니다. 원소가 없거나 최대 하나 밖에 없는 Collection이나 Stream으로 생각하셔도 좋습니다. 직접 다루기에 위험하고 까다로운 null을 담을 수 있는 특수한 그릇으로 생각하시면 이해가 쉬우실 것 같습니다.

Optional 기본 사용법


1. Optional 변수 선언하기

제네릭을 제공하기 때문에, 변수를 선언할 때 명기한 타입 파라미터에 따라서 감쌀 수 있는 객체의 타입이 결정됩니다.

1
2
3
Optional<Order> maybeOrder; // Order 타입의 객체를 감쌀 수 있는 Optional 타입의 변수
Optional<Member> optMember; // Member 타입의 객체를 감쌀 수 있는 Optional 타입의 변수
Optional<Address> address; // Address 타입의 객체를 감쌀 수 있는 Optional 타입의 변수

2. Optional 객체 생성하기

  • Optional.empty()

null을 담고 있는, 한 마디로 비어있는 Optional 객체를 얻어옵니다. 이 비어있는 객체는 Optional 내부적으로 미리 생성해놓은 싱글턴 인스턴스입니다.

1
Optional<Member> maybeMember = Optional.empty();
  • Optional.of(value)

null이 아닌 객체를 담고 있는 Optional 객체를 생성합니다. null이 넘어올 경우, NPE를 던지기 때문에 주의해서 사용해야 합니다.

1
Optional<Member> maybeMember = Optional.of(aMember);
  • Optional.ofNullable(value)

null인지 아닌지 확신할 수 없는 객체를 담고 있는 Optional 객체를 생성합니다. Optional.empty()와 Optional.ofNullable(value)를 합쳐놓은 메소드라고 생각하시면 됩니다. null이 넘어올 경우, NPE를 던지지 않고 Optional.empty()와 동일하게 비어 있는 Optional 객체를 얻어옵니다. 해당 객체가 null인지 아닌지 자신이 없는 상황에서는 이 메소드를 사용하셔야 합니다.

1
2
Optional<Member> maybeMember = Optional.ofNullable(aMember);
Optional<Member> maybeNotMember = Optional.ofNullable(null);

3. Optional이 담고 있는 객체 접근하기

Optional 클래스는 담고 있는 객체를 꺼내오기 위해서 다양한 인스턴스 메소드를 제공합니다. 아래 메소드들은 모두 Optional이 담고 있는 객체가 존재할 경우 동일하게 해당 값을 반환합니다. 반면에 Optional이 비어있는 경우(즉, null을 담고 있는 경우), 다르게 작동합니다. 따라서 비어있는 Optional에 대해서 다르게 작동하는 부분만 설명드리겠습니다.

  • get()

비어있는 Optional 객체에 대해서, NoSuchElementException을 던집니다.

  • orElse(T other)

비어있는 Optional 객체에 대해서, 넘어온 인자를 반환합니다.

  • orElseGet(Supplier<? extends T> other)

비어있는 Optional 객체에 대해서, 넘어온 함수형 인자를 통해 생성된 객체를 반환합니다. orElse(T other)의 게으른 버전이라고 보시면 됩니다. 비어있는 경우에만 함수가 호출되기 때문에 orElse(T other) 대비 성능상 이점을 기대할 수 있습니다.

  • orElseThrow(Supplier<? extends X> exceptionSupplier)

비어있는 Optional 객체에 대해서, 넘어온 함수형 인자를 통해 생성된 예외를 던집니다.

Api


return typemethodDescription
static <T> Optional<T>empty()빈 Optional 객체를 반환한다.
Optional<T>filter(Predicate<? super T> predicate)값이 존재하고 값이 주어진 predicate 의 조건을 일치하는 Optional을 반환한다 아니면 빈 Optional을 반환한다.
<U> Optional <U>flatMap(Function<? super T,? extends Optional<? extends U» mapper)값이 존재하면 값을 적용한 뒤 optional 객체로 반환한다.
Tget()반환되는 값이 존재하면 값을 반환하고 아니면 NoSuchElementException 를 발생시킨다.
voidifPresent(Consumer<? super T> action)반환되는 값이 존재하면 consumer를 수행하고 아니면 아무것도 하지않는다.
voidifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)반환되는 값이 존재하면 consumer를 수행하고 아니면 주어진 Runnable 을 수행한다.
booleanisEmpty()값이 존재하지않으면 true 아니면 false
booleanisPresent()값이 존재하면 true 아니면 false
<U> Optional <U>map(Function<? super T,? extends U> mapper)값이 존재하면 주어진 function에 의해 적용된 값을 포함하는 Optional을 반환한다, 아니면 빈 Optional을 반환한다.
static <T> Optional<T>of(T value)null 이 아닌 Optional을 반환한다.
static <T> Optional<T>ofNullable(T value)Optional을 반환한다 null이면 빈 Optional을 반환한다.
Optional<T>or(Supplier<? extends Optional<? extends T» supplier)Optional이 empty인 경우에 다른 Optional을 반환
TorElse(T other)Optional의 값을 반환하되 null이면 인자를 리턴한다.
TorElseGet(Supplier<? extends T> supplier)Optional의 값을 반환하되 null이면 Supplier에 의해 제공되는 값을 반환한다.
TorElseThrow()Optional의 값을 반환하되 null이면 NoSuchElementException을 발생시킨다.
<X extends Throwable>TorElseThrow(Supplier<? extends X> exceptionSupplier)Optional의 값을 반환하되 null이면 Supplier에 의해 제공되는 Exception을 발생시킨다.
Stream<T>stream()값이 있으면 해당 값만 포함하는 스트림을 반환하고, 그렇지 않으면 빈스트림을 반환한다.

etc

그 밖에도 OptionalInt, OptionalDouble, OptionalInt, OptionalLong 도 있습니다.

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
    OptionalInt opt1 = OptionalInt.empty();
    OptionalInt opt2 = OptionalInt.of(0);

    System.out.println("opt1.isEmpty() = " + opt1.isEmpty());   // true
    System.out.println("opt2.isEmpty() = " + opt2.isEmpty());   // false
    System.out.println("opt2.equals(opt1) = " + opt2.equals(opt1)); // false

}

Github source

references

This post is licensed under CC BY 4.0 by the author.