예외 던지기
진짜 예외적인 상황일 때만 사용해야 함 (item 69)
예외를 생성할 때 스택 추적 전체를 캡처하므로 비용이 큼
→ 예외가 발생하면 스택 추적 정보를 포함한 예외 객체가 생성되는데 예외를 자주 던지면 이 비용이 누적되어 성능 저하를 일으킬 수 있음
<aside> 🏷️
예외를 던질 때의 비용 (스택 추적에 포함되는 정보)
null 반환
// 옵셔널을 사용하지 않았을 때
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;
}
// 옵셔널을 사용할 때
public static <E extends Comparable<E>>
Optional<E> max(Collection<E> c) {
if(c.isEmpty()){
return Optional.empty();
}
...
return Optional.of(result);
}
→ 빈 옵셔널은 Optional.empty()로, 값이 있으면 Optional.of(value)를 사용
옵셔널을 사용하면,,
ifPresent()
나 orElse()
와 같은 메서드를 통해 명시적으로 처리할 수 있음→ 옵셔널을 반환하는 메서드는 예외를 던지는 메서드보다 사용하기 쉽고, null을 반환하는 메서드보다 오류 가능성이 적음
Option.value에 null을 넣으면 NullPointerException 발생
옵셔널을 반환하는 메서드에서는 절대 null을 반환하지 말자
orElse - 기본값 지정
String lastWordInLexicon = max(words).orElse("단어 없음");
orElseThrow - 원하는 예외 던질 수 있음
Toy myTody = max(toys).orElseThrow(TemperTantrumException::new);
get - 항상 값이 채워져 있다고 가정
Element lastNobleGas = max(Elements.NOBEL_GASES).get();
→ 안전하지 않은 듯?
orElseGet - 기본값을 설정하는 비용이 클 때
opMember.orElseGet(MainRunner::getCommon)
→ 값이 필요할때 Supplier 를 사용하여 생성하므로 초기 설정 비용을 낮출 수 있음
isPresent - 옵셔널이 채워져 있으면 true, 아니면 false 반환
opMember.isPresent()
컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안 된다.
Optional<List<Integer>> optionalList = Optional.of(new ArrayList<>());
if (optionalList.isPresent() && !optionalList.get().isEmpty()) {
// 리스트에 값이 있을 때 처리
}
→ ArrayList는 이미 isEmpty() 메서드를 제공하고 있으므로 Optional이 불필요
→ 위 코드처럼 컨테이너 타입에는 이미 빈 상태를 처리할 수 있는 방법을 제공해주므로 옵셔널로 감싸면 혼란을 초래할 수 있음