Java / Optional<T>

김선호·2022년 10월 3일
0

Java 문법

목록 보기
13/15

T 타입 객체의 래퍼 클래스 - Optional<T>

public final class Optional<T> {
  private final T value; // T타입의 참조변수 
        ...
}
  • null을 직접 다루는 것은 위험하고, null을 체크하기 위해 if문을 사용하는 것은 코드가 지저분해지는 단점이 있다.
  • Optional<T> 은 ‘T타입의 객체’ 감싸는 래퍼 클래스이며, Optional<T> 를 가리키는 참조변수는 null 이 될 수 없기 때문에(Optioanl<T> 객체가 null 일 수는 있지만, 해당 객체를 가리키는 참조변수는 Optional<T> 객체의 주솟값을 가지므로) 위와 같은 null 과 관련된 문제들을 해결할 수 있다.

1. Optional<T> 객체 생성하기

// Optional<T> 객체를 생성하는 다양한 방법
String str = "abc";

Optional<String> optVal = Optional.of(str);
Optional<String> optVal = Optional.of("abc");
Optional<String> optVal = Optional.of(null);         // NullPointerExceptino 발생
Optional<String> optVal = Optional.ofNullable(null); // OK

1-1) 메모리구조로 이해하는 Optinal<T> 객체 생성

String str = "abc";
Optional<String> optVal = Optional.of(str);

  • Optinal객체는 참조하는 String 객체의 레퍼런스를 가진다.
  • 변수 strnull이 될 수 있으나, 그림에서 알 수 있듯이 변수optVal 은 절대 null이 될 수 없다. (Optinal객체의 주솟값을 가지므로)

1-2) 참조변수가 null 일 가능성이 있다면, of() 대신 ofNullable()을 사용하라

Optional<String> optVal = Optional.of(null);         // NullPointerExceptino 발생
Optional<String> optVal = Optional.ofNullable(null); // OK
  • Optional 객체가 null 이기 위해서는 ofNullable()을 이용해야한다. of() 를 사용하면 NPE가 발생하기 때문이다.

1-3) null 대신 빈 Optional<T> 객체를 사용하자

Optional<String> optVal = null; // 널로 초기화. 바람직하지 않음
Optional<String> optVal = Optional.<String>empty(); //빈 객체로 초기화
  • Optional 타입의 참조변수를 기본값으로 초기화 할 때는 empty() 를 사용하자.
    • null 을 이용해 초기화할 수 있지만 이는 앞서 설명한 null 을 사용함으로써 생기는 문제들을 야기하기 때문에 바람직하지 않다.

2. Optional 객체의 값 가져오기

2-1) Optinal 객체의 값을 가져오는 방법 - get(), orElse(), orElseGet(), orElseThrow()

// Optinal 객체의 값을 가져오는 방법 - get(), orElse(), orElseGet(), orElseThrow()
Optinal<String> optVal = Optional.of("abc");

String str1 = optVal.get(); // optVal에 저장된 값을 리턴. null이면 예외 발생
String str2 = optVal.orElse(""); // optVal이 null일 때는 ""를 리턴
String str3 = optVal.orElseGet(String::new); // 람다식 사용가능 () -> new String();
String str4 = optVal.orElseThrow(NullPointerException::new); // null이면 예외 발생
  • Optional 객체에 저장된 값을 가져오기 위해서는 get(), orElse(), orElseGet(), orElseThrow() 메서드를 사용할 수 있다.
  • get() 메서드는 Optional 객체가 null일 때 NoSuchElementException 을 발생시키므로, orElse() 또는 orElseGet() 을 사용하도록 하자.

2-2) Optional객체가 null이 아닐 때 어떤 행동을 취하고 싶다면 - isPresent(), ifPresent()

// isPresent()
if (Optional.ofNullable(str).isPresent()) { // if (str! = null) {}
		System.out.println(str);
}

// ifPresent(Consumer<T> block)
Optional.ofNullable(str).ifPresent(System.out::println); // str이 null이 아닐 때 실행
  • isPresent() 는 Optional 객체가 null이면 false를, 아니면 true를 리턴하는 메서드이다.
  • ifPresent(Consumer<T> block) 는 값이 있으면 주어진 람다식을 실행하고, 없으면 아무일 도 하지 않는다.

2-3) Stream처럼 Optional객체에도 filter(), map(), flatmap()을 사용할 수 있다.

int result = Optional.of("123")
                .filter(x -> x.length() > 0)
                .map(Integer::parseInt).orElse(-1);

Stream처럼 Optional 객체에도 filter(), map(), flatmap()을 사용할 수 있다. 단, Optinal객체의 값이 null이라면 이 메서드들은 아무 일도 하지 않는다.


📚 본 포스팅은 책 ‘Java의 정석 3판 - 남궁성 저’를 읽고 정리한 글입니다.

profile
Every Run, Learn Counts.

0개의 댓글