일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- SQL쿡북
- 알고리즘분석
- jpa
- 기술면접
- 인덱스
- 혼공SQL
- 네트워크
- 이펙티브 자바
- react
- aop
- 인프런김영한
- 알고리즘
- 스프링부트와AWS로혼자구현하는웹서비스
- DDD
- 도메인 주도 개발 시작하기
- AWS
- CleanCode
- 인프런백기선
- 클린코드
- 자바예외
- 이팩티브 자바
- MariaDB
- java
- 자료구조
- 자바
- AWS RDS
- vue.js
- mysql
- 자바스터디
- 이펙티브자바
- Today
- Total
기록이 힘이다.
[이펙티브 자바]아이템55. 옵셔널 반환은 신중히 하라 본문
자바 8 전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지가 두 가지 있었다. 예외를 던지거나, (반환 타입이 객체 참조라면) null을 반환하는 것이다.
자바 버전이 8로 올라가면서 또 하나의 선택지가 생겼다. 그 주인공인 Optional<T>는 null이 아닌 T타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다. 옵셔널은 원소를 최대 1개 가질 수 있는 ‘불변’ 컬렉션이다.
보통은 T를 반환해야 하지만 특정 조건에서는 아무것도 반환하지 않아야 할 때 T 대신 Optional<T>를 반환하도록 선언하면 된다. 옵셔널을 반환하는 메서드는 예외를 던지는 메서드보다 유연하고 사용하기 쉬우며, null을 반환하는 메서드보다 오류 가능성이 작다.
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);
}
옵셔널을 반환하는 메서드에서는 절대 Null을 반환하지 말자. 옵셔널을 도입한 취지를 완전히 무시하는 행위다.
public static <E extends Comparable<E>>
Optional<E> max(Collection<E> c) {
return c.stream().max(Comparator.naturalOrder());
}
그렇다면 null을 반환하거나 예외를 던지는 대신 옵셔널 반환을 선택해야 하는 기준은 무엇인가?
옵셔널은 검사 예외와 취지가 비슷하다. 즉, 반환 값이 없을 수도 있음을 API 사용자에게 명확히 알려준다.
- 기본값을 정해둘 수 있다.
String lastWordInLexicon = max(words).orElse("단어 없음...");
- 원하는 예외를 던질 수 있다. =⇒ 예외 생성 비용은 들지 않는다.
Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);
- 항상 값이 채워져 있다고 가정한다. =⇒ 아닐시, NoSuchElementException 발생
Element lastNobleGas = max(Elements.NOBLE_GASES).get();
기본값을 설정하는 비용이 아주 커서 부담이 될 때가 있다. Supplier<T>를 인수로 받는 orElseGet, filter, map, flatMap, ifPresent가 있다.
여전히 적합한 메서드를 찾지 못했다면 isPresent 메서드를 살펴보자. 안전밸브 역할의 메서드로, 옵셔널이 채워져 있으면 true를, 비어 있으면 false를 반환한다.
streamOfOptionals
.filter(Optional::isPresent) 옵셔널에 값이 있다면
.map(Optional::get) 그 값을 꺼내 스트림에 매핑한다.
자바 9에서는 Optional에 stream() 메서드가 추가되었다. 이 메서드는 Optional을 stream으로 변환해주는 어댑터다.
streamOfOptionals
.flatMap(Optional::stream)
반환값으로 옵셔널을 사용한다고 해서 무조건 득이 되는 것은 아니다. 컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안된다.
빈 Optional<List<T>>보다는 빈 List<T>를 반환하는 게 좋다.
기본규칙
결과가 없을 수 있으며, 클라이언트가 이 상황을 특별하게 처리해야 한다면 Optional<T>를 반환한다.
박싱된 기본 타입을 담은 옵셔널을 반환하는 일은 없도록 하자.
옵셔널을 컬렉션의 키, 값, 원소나 배열의 원소로 사용하는 게 적절한 상황은 거의 없다.
옵셔널 반환에는 성능 저하가 뒤따르니, 성능에 민감한 메서드라면 null을 반환하거나 예외를 던지는 편이 나을 수 있다.
'JAVA' 카테고리의 다른 글
왜 우리는 비검사 예외를 선호하는가?(UncheckedException) (0) | 2023.04.13 |
---|---|
[이펙티브 자바]아이템 57 지역변수의 범위를 최소화하라 (0) | 2023.04.11 |
[이펙티브 자바] 아이템45 스트림은 주의해서 사용하라 (0) | 2023.04.07 |
[이펙티브 자바]아이템44 표준 함수형 인터페이스를 사용하라 (0) | 2023.04.07 |
[이펙티브 자바] 6장 열거타입과 애너테이션 (0) | 2023.03.29 |