반응형
가변인수 메서드
가변인수(varargs) 메서드와 제네릭은 함께 사용이 어렵다.
가변인수는 메서드에 넘기는 인수의 개수를 클라이언트가 조절할 수 있게 해준다.
가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어진다.
그런데 내부로 감춰야 했을 이 배열을 클라이언트에 노출시키는 문제가 생겼다. 그 결과 varargs 매개변수에 제네릭이나 매개변수화 타입이 포함되면 알기 어려운 컴파일 경고가 발생한다.
static void dangerous(List<String>... stringLists) {
List<Integer> intList = List.of(2);
Object[] objects = stringLists;
objects[0] = intList; // 힙 오염
/* stringList 는 Integer 타입으로 변경됨 */
String s = stringLists[0].get(0); // ClassCastException 발생
}
@SafeVaragrs
메서드 작성자가 이 메서드가 '타입안전함'을 보장하는 장치.
소비자(사용자)가 Warning을 컨트롤 하지 않아도 된다.
메서드가 '타입안전함'을 확신하는 방법
- 매개변수 배열이 순수하게 '인수들을 전달하는 일'만 한다면 그 메서드는 안전하다.
제네릭 varargs 매개변수 안전하게 사용하는 방법
@SafeVarargs
static <T> List<T> flatten(List<? extends T>... lists) {
List<T> result = new ArrayList<>();
for (List<? extends T> list : lists) {
result.addAll(list);
}
return result;
}
flatten 메서드는 임의 개수 리스트를 인수도 받아, 받은 순서대로 그 안의 모든 원소를 하나의 리스트로 옮겨 담아 반환한다. 이 메서드는 제네릭 varargs 매개변수를 안전하게 사용하는 예다. 따라서 @SafeVarargs 어노테이션도 달아야한다.
@SafeVarargs 어노테이션을 사용할때는 제네릭이나 매개변수화 타입의 varargs 매개변수를 받는 모든 메서드에 @SafeVarargs를 달아라. 그래야 사용자를 헷갈리게 하는 컴파일러 경고를 없앨 수 있다. 이 말은 안전하지않은 varargs 메서드는 절대 작성해서는 안된다는 뜻이기도 하다.
1. varargs 매개변수 배열에 아무것도 저장하지 않는다.
2. 그 배열(혹은 복제본)을 신뢰할 수 없는 코드에 노출하지 않는다.
반응형
'1_스터디' 카테고리의 다른 글
[EffectiveJava] ITEM 33. 타입 안전 이종 컨테이너를 고려하라 (0) | 2022.08.15 |
---|---|
[Effectvie Java] ITEM 31. 한정적 와일드카드를 사용해 API 유연성을 높이라. (0) | 2022.08.13 |
[EffectiveJava] ITEM 30. 이왕이면 제네릭 메서드로 만들라 (0) | 2022.08.12 |
[EffectiveJava] ITEM 29. 이왕이면 제네릭 타입으로 만들라 (0) | 2022.08.11 |
[EffectiveJava] ITEM 28. 배열보다는 리스트를 사용하라 (0) | 2022.08.10 |