[Effective Java] 아이템55 - 옵셔널 반환은 신중히 하라

자바8 이전에는 메서드가 값을 반환할 수 없을 때 취할 수 있는 선택지가 두 가지가 있었다.

  1. null 반환
  2. Exeption 반환

예외는 “진짜 예외적인 상황에서만” 사용해야 하며 null 반환은 클라이언트 측에서 별도의 null 처리 코드를 추가해야한다. (빠짐없이)

자바8 은 Optional 을 추가해서, 반환값이 없을 수도 있음을 API 사용자에게 명확히 알려준다. (Checked Exception 과 취지가 비슷하다)

Optional 을 받은 클라이언트는 null 일 경우 기본값을 설정하거나, 예외를 던질 수 있다.

  • 기본값 저장 (orElse)
    String lastWordInLexicon = max(words).orElse("단어 없음");
    
  • 예외 생성 (orELseThrow)
      String lastWordInLexicon = max(words).orELseThrow("Exception::new");
    
  • 기본값을 생성하는 데 비용이 좀 든다면 Supplier 를 인수로 받는 orElseGet 을 사용하자. 값이 처음으로 필요할때만 값을 생성하므로 초기 설정 비용을 낮출 수 있다.
      public static void main(String[] args) {
      Optional<String> optionalTest = Optional.ofNullable(null);
      System.out.println(optionalTest.orElseGet(() -> "Null 입니다"));
      }
    

반환값으로 옵셔널을 사용한다고 해서 무조건 득이 되는 건 아니다. 컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안된다. 예를 들어, Optioal<List> 를 반환하기 보다는 List 를 반환하는게 좋다

결과가 없을 수 있으며, 클라이언트가 이 상황을 특별하게 처리해야 한다면 Optional 를 반환하자!

Optional 도 엄연히 객체이기 때문에 박싱된 기본 타입을 담은 옵셔널은 기본 타입 자체보다 무거울 수 밖에 없다. 값을 두겹이나 감싸기 때문이다. 따라서 OptionalInt, OptionalLong, OptionalDouble 클래스들이 있다.


  • 옵셔널을 맵의 값으로 사용하면 절대 안된다.
    • 쓸제없이 복잡성만 높여서 혼란과 오류 가능성이 높아진다.
  • 옵셔널을 인스턴스 필드에 저장해도 될까?
    • 필드들이 기본 타입이라 값이 없음을 나타낼 방법이 마땅치 않으면 getter 메서드로 옵셔널을 반환하게 해주는 것도 방법이다.

댓글남기기