Item 54 - null이 아닌 빈 컬렉션이나 배열을 반환하라
컬렉션이나 배열이 비었을 때 null을 반환하면? 🐛
1
2
3
4
5
6
7
8
9
private final List<Cheese> cheesesInStock = ...;
/**
* @return 매장 안의 모든 치즈 목록 반환한다.
* 단, 재고가 하나도 없다면 null 을 반환한다.
*/
public List<Cheese> getCheeses() {
return cheesesInStock.isEmpty() ? null : new ArrayList<>(cheesesInStock);
}
- null 상황을 처리하는 로직을 추가로 작성해야 한다.
클라이언트 측, 방어코드
1
2
List<Cheese> cheeses = shop.getCheeses();
if (cheeses != null && cheeses.contains(Cheese.STILTON)){ ... } // null 예외 처리
- 클라이언트에서 이러한 방어 코드를 빼먹으면 NPE 오류가 발생할 수 있다.
- 이 같은 추가 로직은 서비스를 복잡하게 만들며, 실수를 일으킬 수 있다.
위 방식을 쓰는 사람들의 의견
빈 컨테이너(컬렉션, 배열)를 할당하는데도 비용이 드니 null을 반환하는 쪽이 낫다(…?)
과연 그럴까 ?
빈 컬렉션이나 배열을 만드는 것이 문제점이 아닌 이유
- 성능 저하의 주범이라고 확인되지 않는 이상 이 정도의 성능 차이는 신경 쓸 수준이 못된다.
- 빈 컬렉션과 배열을 굳이 새로 할당하지 않고도 반환할 수 있다.
그러므로 null이 아닌 빈 컬렉션이나 배열을 반환하자! 🛠️
컬렉션의 경우
빈 컬렉션을 반환하는 방법
1
2
3
public List<Cheese> getCheeses() {
return new ArrayList<>(cheesesInStock);
}
빈 컬렉션을 매번 생성하는 것이 성능상 문제가 된다면,
1
2
3
4
public List<Cheese> getCheeses() {
return cheesesInStock.isEmpty() ? Collections.emptyList()
: new ArrayList<>(cheesesInStock);
}
Collections.emptyList()
을 이용하여 매번 똑같은 빈 불변 컬렉션을 반환하면 된다.Collectionse.emptyList()
,Collectionse.emptyMap()
,Collectionse.emptySet()
…
배열의 경우
길이가 0일 수도 있는 배열을 반환하는 방법
1
2
3
public Cheese[] getCheeses() {
return cheesesInStock.toArray(new Cheese[0]);
}
빈 배열을 매번 생성하는 것이 성능상 문제가 된다면,
1
2
3
4
5
private static final Cheese [] EMPTY_CHEESE_ARRAY = new Cheese[0];
public Cheese[] getCheeses() {
return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
}
- 길이 0인 배열을 미리 선언해두고, 그 배열을 반환하면 된다.
- 단순히 성능 개선할 목적이라면 toArray에 넘기는 배열을 미리 할당하는 건 추천하지 않는다. - 오히려 성능이 떨어진다는 연구 결과도 있다.
💡 정리
- null이 아닌, 빈 배열이나 컬렉션을 반환하자.
- null을 반환하는 API는 성능이 좋은 것도 아니고, 오히려 서비스 로직을 복잡하게 만든다.
This post is licensed under CC BY 4.0 by the author.