자바 8 이전
자바 8 이전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지가 두 가지 있었다.
이 두 방식 모두 허점이 존재한다. 예외는 진짜 예외적인 상황에만 사용 해야 하고, null을 반환하는 경우는 별도의 null 처리 코드가 필요하다.
자바 8 이후
자바 버전 8의 등장 이후 또 하나의 선택지가 생겼다.
**Optional**는 null이 아닌 T타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다.
옵셔널은 원소를 최대 1개 가질 수 있는 불변 컬렉션이다. 보통은 T를 반환해야 하지만 특정 조건에서는 아무것도 반환하지 않아야 할 때 T 대신 Optional를 반환하도록 선언하면 된다.
- 예외를 던지는 메서드 보다 사용하기 쉽고, Null을 반환하는 메서드 보다 안전하다.
public static <E extends Comparable<E>> Optinal<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.empty()로 만들고, 값이 든 옵셔널은 Optional.of(value)로 생성했다. Optional.of(value)에 null을 넣으면 NullPointerException을 던지니 주의하자.
- 옵셔널을 반환하는 메서드에서는 절대 null을 반환하지 말자.
Null을 반환하거나 예외를 던지는 대신 옵셔널 반환을 선택하는 기준
옵셔널은 검사 에외와 취지가 비슷하다. 즉 반환 값이 없을 수도 있음을 API 사용자에게 명확히 알려준다. #7
결과가 없을 수 있으며, 클라이언트가 이 상황을 특별하게 처리해야 한다면 Optional를 반환한다.
// 옵셔널 활용1 - 기본값을 정해둘 수 있다.
String lastWordInLexicon = max(words).orElse("단어 없음...");
// 옵셔널 활용2 - 원하는 예외를 던질 수 있다.
Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);
// 옵셔널 활용3 - 항상 값이 채워져 있다고 가정한다.
Element lastNobleGas = max(Elements.NOBLE_GASES).get();
// 옵셔널 활용4 - 옵셔널의 여부를 true / false로 반환해줌
boolean check = parentProcess.isPresent();
반환 값으로 옵셔널을 사용한다고 무조건 득이 되는 건 아니다.
컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안 된다.
빈 Optional<List>를 반환하기보다는 빈 List를 반환하는 게 좋다. #27
추가
박싱된 기본 타입을 담는 옵셔널은 기본 타입 자체보다 무겁다. 따라서 자바에는 int, long, double 전용 옵셔널 클래스들을 준비해놨다.
- OptionalInt
- OptionalLong
- OptionalDouble
옵셔널을 맵의 값으로 사용하지 마라!
옵셔널을 컬렉션의 키, 값, 원소나 배열의 원소로 사용하는 게 적절한 상황은 거의 없다.
정리
갑을 반환하지 못할 가능성이 있고, 호출할 때마다 반환값이 없을 가능성을 염두에 둬야하는 메서드라면 옵셔널을 반환해야 할 상황일 수 있다.
성능에 민감하다면 null을 반환하거나 예외를 던지는게 나을 수 있다.
자바 8 이전
자바 8 이전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지가 두 가지 있었다.
이 두 방식 모두 허점이 존재한다. 예외는 진짜 예외적인 상황에만 사용 해야 하고, null을 반환하는 경우는 별도의 null 처리 코드가 필요하다.
자바 8 이후
자바 버전 8의 등장 이후 또 하나의 선택지가 생겼다.
**Optional**는 null이 아닌 T타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다.
옵셔널은 원소를 최대 1개 가질 수 있는 불변 컬렉션이다. 보통은 T를 반환해야 하지만 특정 조건에서는 아무것도 반환하지 않아야 할 때 T 대신 Optional를 반환하도록 선언하면 된다.
적절한 정적 팩터리를 사용하면 손쉽게 옵셔널을 사용할 수 있다. 다음은 빈 옵셔널을 Optional.empty()로 만들고, 값이 든 옵셔널은 Optional.of(value)로 생성했다. Optional.of(value)에 null을 넣으면 NullPointerException을 던지니 주의하자.
Null을 반환하거나 예외를 던지는 대신 옵셔널 반환을 선택하는 기준
옵셔널은 검사 에외와 취지가 비슷하다. 즉 반환 값이 없을 수도 있음을 API 사용자에게 명확히 알려준다. #7
결과가 없을 수 있으며, 클라이언트가 이 상황을 특별하게 처리해야 한다면 Optional를 반환한다.
반환 값으로 옵셔널을 사용한다고 무조건 득이 되는 건 아니다.
컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안 된다.
빈 Optional<List>를 반환하기보다는 빈 List를 반환하는 게 좋다. #27
추가
박싱된 기본 타입을 담는 옵셔널은 기본 타입 자체보다 무겁다. 따라서 자바에는 int, long, double 전용 옵셔널 클래스들을 준비해놨다.
옵셔널을 맵의 값으로 사용하지 마라!
옵셔널을 컬렉션의 키, 값, 원소나 배열의 원소로 사용하는 게 적절한 상황은 거의 없다.
정리
갑을 반환하지 못할 가능성이 있고, 호출할 때마다 반환값이 없을 가능성을 염두에 둬야하는 메서드라면 옵셔널을 반환해야 할 상황일 수 있다.
성능에 민감하다면 null을 반환하거나 예외를 던지는게 나을 수 있다.