[이펙티브 자바 54] null 이 아닌, 빈 컬렉션이나 배열을 반환하라

박상준·6일 전
0

이펙티브 자바

목록 보기
16/16

문제 상황

private final List<Cheese> cheesesInStock = ...;

/**
 * @return 매장 안의 모든 치즈 목록을 반환한다.
 * 단, 재고가 하나도 없다면 null을 반환한다.
 */
public List<Cheese> getCheeses() {
    return cheesesInStock.isEmpty() ? null : new ArrayList<>(cheesesInStock);
}
  • 에서 배열이 비어있는 경우에 단순히 null 을 반환하는 코드가 있다고 생각해보자.

해당 코드상의 문제점

  • 클라이언트에서 null 값에 대해 처리하는 추가적인 코드를 작성해야한다.
  • 방어 코드를 빼먹는 경우 오류가 발생할 수 있는데,
    • 객체가 0일 가능성이 거의 없는 상황에서는 수년 후에나 오류가 발생가능

클라이언트 방어 코드

List<Cheese> cheeses = shop.getCheeses();
if (cheeses != null && cheeses.contains(Cheese.STILTON)) {
    System.out.println("좋았어, 바로 그거야.");
}

반론

  • 빈 컨테이너 == new ArrayList() ; , 등등.
    • 을 할당하는 것 자체가 비용이 들기에 null 을 반환하는 것이 낫다.
  • 대답
    • 성능 분석 결과, 해당 할당이 성능 저하의 주범이 될 수 가 없음.
    • 빈 컬렉션과 배열은 새로 할당하지 않고도 반환이 가능하다.

해결방안

  1. 빈 컬렉션 반환

    public List<Cheese> getCheeses() {
        return new ArrayList<>(cheesesInStock);
    }
  2. 최적화:

    • 매번 같은 불변 컬렉션을 반환
    • 불변 객체는 자유롭게 공유가 가능하다.
        public static List<Integer> getArr() {
            List<Integer> arr = new ArrayList<>();
            return arr.isEmpty() ? Collections.emptyList() : arr;
        }
      • Collections.emptyList(), emptySet(), emptyMap() 등이 가능하다.
    • 이는 매번 arrayList 등의 객체를 매번 생성하는것이 아니라,
      public static final <T> List<T> emptyList() {
          return (List<T>) EMPTY_LIST;
      }
      • 그냥 이미 선언되어 있는 EMPTY_LIST 를 그대로 반환한다.

  1. null 이 아니라, 빈 배열이나 컬렉션 반환
  2. null 반환하는 API 는 사용하기가 어렵고, 오류 처리 코드가 늘어남
  3. null 반환시 성능상의 이점도 없음
profile
이전 블로그 : https://oth3410.tistory.com/

0개의 댓글