옵셔널 반환은 신중히 하라

김종준·2023년 8월 2일
0

이펙티브자바

목록 보기
48/63

옵셔널 반환은 신중히 하라

자바 8전에 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지는 다음과 같다.

  • 예외를 던진다.
  • null을 반환한다.

하지만 예외는 정말 예외적인 상황에서만 사용해야 하며 예외를 생성할 때 스택 추적 전체를 캡처하는 비용도 만만치 않다.

null을 반환한다면 null을 처리하는 코드를 추가해야 한다.

그렇지 않다면 반환된 null 값이 어딘가에서 NullPointerException을 일으킨다.

자바 버전이 8로 올라가면서 선택지가 추가되었는데 그 주인공은 Optional이다.

Optional은 null이 아닌 T 타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다.

아무것도 담지 않은 옵셔널은 '비었다'고 말한다.

반대로 어떤 값을 담은 옵셔널은 '비지 않았다'고 한다.

옵셔널은 원소를 최대 1개 가질 수 있는 '불변' 컬렉션이다.

보통은 T를 반환해야 하지만 특정 조건에서는 아무것도 반환하지 않아야 할 때 T대신 Optional를 반환하도록 선언하면 된다.

그러면 유요한 반환값이 없을 대는 빈 결과를 반환하는 메서드가 만들어진다.

옵셔널을 반환하는 메서드는 예외를 던지는 메서드보다 유연하고 사용하기 쉬우며, null을 반환하는 메서드보다 오류 가능성이 작다.

옵셔널을 반환하는 경우 주의할 점이 있는데 옵셔널을 반환하는 메서드에서는 절대 null을 반환하지 말아야 한다.

옵셔널을 도입한 취지를 완전히 무시하는 행위다.

그럼, null을 반환하거나 예외를 던지는 대신 옵셔널 반환을 선택해야 하는 기준은 무엇일까?

옵셔널은 검사 예외와 취지가 비슷하다.

즉, 반환값이 없을 수도 있음을 API 사용자에게 명확히 알려준다.

이제 옵셔널 메서드에 대해 알아보자.

  • .orElse : 기본값을 정해둔다.
  • .orElseThrow : 원하는 예외를 던진다.
  • .get : 항상 값이 채워져 있다고 가정한다.
  • .isPresent : 값이 채워져 있는지 확인한다.

이때 기본값을 설정하는 비용이 아주 많이 들어서 부담이 될 때가 있다.

그럴 때는 Supplier를 인수로 받는 orElseGet을 사용하면, 값이 처음 필요할 때 Supplier 를 사용해 생성하므로 초기 설정 비용을 낮출 수 있다.

그리고 반환 값으로 옵셔널을 사용한다고 해서 무조건 득이 되는 것은 아니다.

컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안 된다.

그리고 옵셔널을 인스턴스 필드에 저장해 두는 게 필요한 경우가 있을까?

이런 상황은 대부분 필수 필드를 갖는 클래스와, 이를 확장해 선택적 필드를 추가한 하위 클래스를 따로 만들어야 함을 암시하는 '나쁜 냄새'다.

하지만 지만 가끔은 적절한 상황도 있다.

0개의 댓글