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

2022. 11. 18. 22:58· BE/Java
목차
  1. 아이템 55. 옵셔널 반환은 신중히 하라
  2.  
  3.  
반응형

EFFECTIVE JAVA(이펙티브 자바)

 

 

이 포스팅에서 작성하는 내용은 EFFECTIVE JAVA(이펙티브자바) 에서 발췌하였습니다.


아이템 55. 옵셔널 반환은 신중히 하라

 

메서드가 특정 조건에서 값을 반환할 수 없을 때 처리하는 방법

~ 자바 7

  • 예외를 던지거나, (반환 타입이 객체 참조라면) null을 반환
  • 예외는 진짜 예외적인 상황에서만 사용해야 하며 예외를 생성할 때는 스택 추적 전체를 캡처하므로 비용이 만만치 않다.
  • null을 반환하면 이런 문제가 생기진 않지만, 별도의 null 처리 코드를 추가해야 한다.

 

자바 8 이후의 새로운 방법 : Optional<T>

  • Optional<T>는 null 이 아닌 T 타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다.
  • 아무것도 담지 않은 Optional은 ‘비었다’ 라고 한다.
  • 반대로 어떤 값을 담은 Optional은 ‘비지 않았다’ 라고 한다.
  • Optional은 원소를 최대 1개 가질 수 있는 ‘불변’ 컬렉션이다.
  • 보통은 T를 반환해야 하지만 특정조건에서는 아무것도 반환하지 말아야할 때 T 대신 Optional<T>를 반환하도록 선언하면 된다.
  • Optional을 반환하는 메서드는 예외를 던지는 메서드보다 유연하고 사용하기 쉬우며, null을 반환하는 메서드보다 오류 가능성이 작다.

 

 

ex 1) 컬렉션에서 최댓값을 구하는 예(컬렉션이 비어있는 경우 예외를 던짐)

public static <E extends Comparable<E>> E max (Collection<E> c) {
	if(c.isEmpty())
    	throw new IllegalArgumentException("빈 컬렉션");
    
    E result = null;
    for (E e : c )
    	if (result==null || e.compareTo(result) >0)
        	result = Objects.requireNonNull(e);
            
    return result;
}

 

 

ex 2) 컬렉션에서 최댓값을 구해 Optional<E>로 반환하는 예

public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
   if (c.isEmpty())
   		return Optional.empty();
        
   E result = null;
   for (E e : c)
   		if(result==null||e.compareTo(result)>0)
        	result = Objects.requireNonNull(e);
            
   return Optional.of(result);
}
  • Optional을 반환하는 법은 적절한 정적 팩터리를 사용해 Optional을 생성해주기만 하면 된다.
  • 이 코드에서는 두 가지 팩터리를 사용했다.
    • 빈 Optional은 Optional.empty()로 만들고,
    • 값이 든 Optional.of(value)로 생성했다
  • 참고로, Optional.of(value)에 null을 넣으면 NPE가 발생하니 주의해야 한다.
  • Optional을 반환하는 메서드에는 절대 null을 반환하지 말자.

 

 

ex 3) ex 2의 코드를 스트림 버전으로 작성한 예

public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
	return c.stream().max(Comparator.naturalOrder());
}
  • 이렇게 스트림 버전으로 작성하면 Stream의 max 연산이 필요한 Optional을 생성해준다. (비교자를 명시적으로 전달해야함)
  • Optional은 검사 예외와 취지가 비슷하다.
  • 즉, 반환값이 없을 수도 있음을 API를 사용하는 사람에 명확히 알려준다.
  • 메서드가 Optional을 반환한다면 클라이언트는 값을 받지 못했을 때 취할 행동을 선택해야 한다.

 

 

ex 4) 기본값을 사용하는 예

String lastWordInLexicon = max(words).orElse("단어 없음...");
  • 기본값을 설정하는 비용이 부담이 될 때가 있따.
  • 그럴 때는 Supplier<T>를 인수로 받는 orElseGet을 사용하면, 값이 처음 필요할 때 Supplier<T>를 사용해 생성하므로 초기 설정 비용을 낮출 수 있다.

 

 

ex 5) 원하는 예외를 던지는 예

Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);

 

 

ex 6) Optional에 항상 값이 있다고 확신하여 바로 꺼내서 사용하는 예

Element lastNobleGas = max(Elements.NOBLE_GASES).get();

 

 

isPresent Method

  • 안전 밸브 역할의 메서드로, Optional에 값이 있으면 true를, 비어있으면 false를 반환
  • 이 메서드로 원하는 모든 작업을 수행할 수 있지만, 신중히 수행해야 한다.

 

 

Optional 유의점

  • 반환값으로 Optional을 사용한다고해서 항상 좋은 것은 아니다.
  • 컬렉션, 스트림, 배열, Optional 값은 컨테이너 타입은 Optionalfh 감싸면 안된다.
  • 빈 Optional<List<T>>를 반환하기보다 빈 List<T>를 반환하는게 좋다. (Optional 처리 코드를 넣지 않아도 되므로)
  • 어떤 경우에 메서드 반환 타입을 T 대신 Optional<T>로 해야할까? 결과가 없을 수 있으며, 클라이언트가 이 상황을 특별하게 처리해야할 때 Optional<T>를 반환한다.
  • 박싱된 기본 타입들을 Optional에 담아 반환하는 일이 없어야 한다. 대신 아래의 전용 Optional 을 사용하자
    • 박싱된 기본 타입을 담는 Optional : OptinalInt, OptionalLong, OptionalDouble
  • Optional을 컬렉션의 카, 값, 원소나 배열의 원소로 사용하는 게 적절한 상황은 거의 없다.

 

 

정리

  • 값을 반환하지 못할 가능성이 있고, 호출할 때마다 반환값이 없을 가능성을 염두해야한다면 Optional을 반환해야할 상황일 수도 있다.
  • Optional 반환에는 성능 저하가 발생할 수 있으니, 성능에 민감하다면 null을 반환하거나 예외를 던지는 게 나을수도 있다.
  • Optional을 반환값 이외의 용도로 사용하는 경우는 매우 드물다.
반응형

'BE > Java' 카테고리의 다른 글

[Effective Java] 아이템 57. 지역변수의 범위를 최소화하라  (0) 2022.11.22
[Effective Java] 아이템 56. 공개된 API 요소에는 항상 문서화 주석을 작성하라  (0) 2022.11.21
[Effective Java] 아이템 54. null이 아닌, 빈 컬렉션이나 배열을 반환하라  (0) 2022.11.17
[Effective Java] 아이템 53. 가변인수는 신중히 사용하라  (0) 2022.11.16
[Effective Java] 아이템 52. 다중정의는 신중히 사용하라  (0) 2022.11.15
  1. 아이템 55. 옵셔널 반환은 신중히 하라
  2.  
  3.  
'BE/Java' 카테고리의 다른 글
  • [Effective Java] 아이템 57. 지역변수의 범위를 최소화하라
  • [Effective Java] 아이템 56. 공개된 API 요소에는 항상 문서화 주석을 작성하라
  • [Effective Java] 아이템 54. null이 아닌, 빈 컬렉션이나 배열을 반환하라
  • [Effective Java] 아이템 53. 가변인수는 신중히 사용하라
멍목
멍목
개발 관련 새롭게 알게 된 지식이나 좋은 정보들을 메모하는 공간입니다.
반응형
멍목
김멍목의 개발블로그
멍목
전체
오늘
어제
  • 분류 전체보기 (514)
    • BE (190)
      • Spring (21)
      • Java (141)
      • Kotlin (6)
      • JPA (22)
    • FE (33)
      • Javascript (16)
      • Typescript (0)
      • React (5)
      • Vue.js (9)
      • JSP & JSTL (3)
    • DB (32)
      • Oracle (22)
      • MongoDB (10)
    • Algorithm (195)
    • Linux (8)
    • Git (6)
    • etc (42)
    • ---------------------------.. (0)
    • 회계 (4)
      • 전산회계 2급 (4)
    • 잡동사니 (2)

블로그 메뉴

  • 홈
  • 관리

공지사항

인기 글

태그

  • 자바 공부
  • JPA 공부
  • 자기개발
  • 더 자바 애플리케이션을 테스트하는 다양한 방법
  • Oracle
  • MongoDB 공부
  • 자기공부
  • vue3 공부
  • 전산회계 2급 준비
  • java 8
  • 이펙티브 자바
  • 이펙티브자바
  • MongoDB 기초부터 실무까지
  • 코테공부
  • MongoDB with Node.js
  • junit5
  • 프로젝트로 배우는 Vue.js 3
  • 알고리즘 공부
  • 자바 개발자를 위한 코틀린 입문
  • 코틀린
  • 자기 개발
  • 알고리즘공부
  • Java to Kotlin
  • 더 자바 Java 8
  • 자바 테스팅 프레임워크
  • 자바공부
  • 코테 공부
  • JPA
  • Effective Java
  • 자기 공부

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.0
멍목
[Effective Java] 아이템 55. 옵셔널 반환은 신중히 하라
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.