null이 아닌, 빈 배열이나 컬렉션을 반환하라. null을 반환하는 API는 사용하기 어렵고 오료 처리 코드도 늘어난다. 그렇다고 성능이 좋은 것도 아니다.
컬렉션을 반환할 때 빈 컨테이너를 할당하는 데도 비용이 드니 null을 반환하는 쪽이 낫다는 주장이 있다. 하지만 두 가지 면에서 틀린 주장이다.
- 성능 분석 결과 이 할당이 성능 저하의 주범이라고 확인되지 않는 한 이 정도의 성능 차이는 신경 쓸 수준이 못 된다. (item 67)
- 빈 컬렉션과 배열은 굳이 새로 할당하지 않고도 반환할 수 있다.
ex) 빈 컬렉션을 반환하는 올바른 예public List<Cheese> getCheeses() { return new ArrayList<>(cheesesInStock); }
사용 패턴에 따라 빈 컬렉션 할당이 성능을 눈에 띄게 떨어뜨릴 수 있다. 이 경우에는 불변 컬렉션을 반환하면 된다. 이 경우에도 꼭 필요할 때만 사용하며, 성능 개선이 얼마나 됐는지 확인해야 한다.
ex) 최적화 - 빈 컬렉션을 매번 새로 할당하지 않도록 하는 예
public List<Cheese> getCheeses() {
return cheesesInStock.isEmpty() ? Collections.emptyList()
: new ArrayList<>(cheeseInStock);
}
배열을 쓸 때도 마찬가지다. null을 반환하지 말고, 길이가 0인 배열을 반환한다.
ex) 길이가 0일 수도 있는 배열을 반환하는 올바른 방법
public Cheese[] getCheeses() {
return cheeseInStock.toArray(new Cheese[0]);
}
이 방식이 성능을 떨어뜨릴 것 같다면 길이 0짜리 배열을 미리 선언해주고 매번 그 배열을 반환하면 된다. 길이 0인 배열은 모두 불변이기 때문이다.
private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];
public Cheese[] getCheeses() {
return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
}
이 최적화 버전의 getCheeses는 항상 EMPTY_CHEESE_ARRAY를 인수로 넘겨 toArray를 호출한다. 따라서 cheesesInStock이 비었을 때면 언제나 EMPTY_CHEESE_ARRAY를 반환하게 된다. 단순히 성능을 개선할 목적이라면 toArray에 넘기는 배열을 미리 할당하는 건 추천하지 않는다. 오히려 성능이 떨어진다는 연구가 있다.
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
Arrays.copyOf
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
'Java > EffectiveJava' 카테고리의 다른 글
Effective Java Item53. 가변인수는 신중히 사용하라. (0) | 2025.02.22 |
---|---|
Effective Java Item42. 익명 클래스보다는 람다를 사용하라. (1) | 2025.02.16 |
Effective Java Item41. 정의하려는 것이 타입이라면 마커 인터페이스를 사용하라. (0) | 2025.02.16 |
Effective Java Item33. 타입 안전 이종 컨테이너를 고려하라. (1) | 2025.02.09 |
Effective Java Item32. 제네릭과 가변인수를 함께 쓸 때는 신중하라. (0) | 2025.02.09 |