Optional은 Java 8에서 도입된 null 이 올 수 있는 객체들을 감싸는 Wrapper 클래스이다.
Optional은 객체를 한 번 감싸서 저장하여서 저장된 값이 null이더라도 NPE(NullPointerException)가 발생하지 않도록 도와준다.
public final class Optional<T> {
// If non-null, the value; if null, indicates no value is present
private final T value;
기능을 제대로 사용하기 위해서는 이 기능을 만든 의도를 파악해야 한다.
Java Docs 에 써있는 API Note에 따르면 Optional의 의도는 이렇다.
Optional is primarily intended for use as a method return type where there is a clear need to represent "no result," and where using null is likely to cause errors.
A variable whose type is Optional should never itself be null; it should always point to an Optional instance.Optional은 "결과 없음"을 명확하게 표현해야 하거나, null을 사용하면 오류를 발생시킬 가능성이 있는 메서드의 리턴 타입으로 사용한다.
Optional 타입의 객체 자체는 null이 될 수 없고 항상 Optional 인스턴스를 가리켜야 한다.
위 글을 정리해보면, Optional을 사용해야할 때는
이라는 것을 알 수 있다.
또 오라클 기술 블로그에 서술된 Optional 클래스의 중요한 의도가 적혀있다.
It is important to note that the intention of the Optional class is not to replace every single null reference. Instead, its purpose is to help design more-comprehensible APIs so that by just reading the signature of a method, you can tell whether you can expect an optional value. This forces you to actively unwrap an Optional to deal with the absence of a value.
Optional 클래스는 모든 단일 null 참조를 대체하기 위한 의도가 아니다.
중요한 것은 메서드의 시그니처를 읽는 것만으로 메서드의 결과가 nullable한 값을 반환하는지 알 수 있도록, 보다 이해하기 쉬운 API 설계를 할 수 있도록 돕는다.
Optional 클래스에서 제공하는 메서드들을 일부 알아보자.
Optional.empty() - 값이 Null일 경우
Optional<String> empty = Optional.empty();
System.out.println(empty); // Optional.empty
말 그대로 empty optional instance를 반환한다.
유의할 점은 다른 Optional 객체가 비어있는지 확인하고 싶을 때, 이 empty()로 생성된 인스턴스와 ==나 != 연산자로 비교하면 안되고 밑에 설명할 isEmpty()나 isPresent()를 통해 확인해야 한다.
Optional.of() - 값이 Null이 아닌 경우
어떤 데이터가 절대 null이 아니라면 Optional.of()를 통해 생성할 수 있다. 만약 null이라면 NPE 가 발생한다.
Optional<String> hello = Optional.of("HELLO");
Optional.ofNullable() - 값이 null일 수도 있을 경우
null의 가능성이 있는 데이터를 넣을 때 사용한다.
null이 아니라면 그 값을 반환하고, null이라면 Optional.empty를 반환한다.
Optional<String> hello = Optional.ofNullable("HELLO");
Optional<String> empty = Optional.ofNullable(null);
System.out.println(hello); // Optional[HELLO]
System.out.println(empty); // Optional.empty
Optional 객체에 값이 있는지 혹은 없는지 판단하는 메서드
Optional<String> presentObject = Optional.of("something");
System.out.println(presentObject.isPresent()); // true
System.out.println(presentObject.isEmpty()); // false
Optional 객체에 값이 존재한다면 인자로 들어가는 함수를 실행시킴
Optional<String> presentObject = Optional.of("something");
presentObject.ifPresent(System.out::println); // something
Optional 객체에 값이 있다면 그 값을 반환하고 없다면 각 메서드에 맞는 결과를 반환
orElse() 는 인자로 들어가는 값을 반환orElseThrow() 는 NoSuchElementExcpetion을 던지거나 인자로 넣은 예외 반환Optional<String> empty = Optional.empty();
System.out.println(empty.orElse("default value")); // default value
System.out.println(empty.orElseThrow()); // NoSuchElementException 예외 발생
Optional 객체 안에 값을 가져오는 메서드
이 메서드는 사용 전에 Optional의 값이 있는지 확인하는 게 무조건 선행되어야 하기 때문에 orElse()나 orElseThrow()를 사용하는 게 더 안전하다.
만약 이전에 확실하게 값이 체크되었다면 사용할 수 있다.
이 글에서 설명하는 메서드는 이 정도만 간출하여 설명하겠다.
만약 모든 메서드를 알고 싶다면 Optional 문서를 통해 보면 된다.
메서드들이 매우 직관적으로 되어있어서 쉽게 이해할 수 있다.
구글링을 통해 공부를 하던 중 Optional 사용 방법에 대한 올바른 방법을 기술한 좋은 포스팅을 찾았다.
https://dzone.com/articles/using-optional-correctly-is-not-optional
이 글을 참고하여 정리해보자.