728x90
- varargs 매개변수에 제네릭이나 매개변수화 타입이 포함되면 알기 어려운 컴파일 경고가 발생한다.
public class Dangerous {
static void dangerous(List<String>... stringLists) {
List<Integer> intList = List.of(42);
Object[] objects = stringLists;
objects[0] = intList; // 힙 오염 발생
String s = stringLists[0].get(0); // ClassCastException
}
public static void main(String[] args) {
dangerous(List.of("There be dragons!"));
}
}
- 매개변수화 타입의 변수가 다른 객체를 참조하면 힙 오염이 발생한다.
- 위 코드는 한줄한줄만 본다면 이상이 없지만 값을 꺼낼때 문제가 발생한다.
- 즉 제네릭 varargs 배열 매개변수에 값을 저장하는것은 안전하지 않다.
- @SafeVarargs 애너테이션으로 메서드 타입이 안전함을 보장하는 방법도 있다.
- 메서드가 이 배열에 아무것도 저장하지 않는다.
- 그 배열(혹은 복제본)을 신뢰할 수 없는 코드에 노출하지 않는다.
- 임의 개수의 리스트를 인수로 받아, 받은 순서대로 그 안의 모든 원소를 하나의 리스트로 옮겨 담아 반환하는 방법도 있다.
public class FlattenWithVarargs {
@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;
}
public static void main(String[] args) {
List<Integer> flatList = flatten(
List.of(1, 2), List.of(3, 4, 5), List.of(6, 7));
System.out.println(flatList);
}
}
- arargs 매개변수를 List 매개변수로 바꿀 수도 있다.
public class FlattenWithList {
static <T> List<T> flatten(List<List<? extends T>> lists) {
List<T> result = new ArrayList<>();
for (List<? extends T> list : lists)
result.addAll(list);
return result;
}
public static void main(String[] args) {
List<Integer> flatList = flatten(List.of(
List.of(1, 2), List.of(3, 4, 5), List.of(6, 7)));
System.out.println(flatList);
}
}
- 기타
- 예제에 ThreadLocalRandom 클래스 사용이 보이는데 ThreadLocal에 대해서도 알아보면 좋을 듯 하다.
728x90
'공부 > 이펙티브자바' 카테고리의 다른 글
[이펙티브자바]item 33.타입 안전 이종 컨테이너를 고려하라. (0) | 2023.02.17 |
---|---|
[이펙티브자바]item 31.한정적 와일드카드를 사용해 API 유연성을 높이라. (0) | 2023.02.15 |
[이펙티브자바]item 30.이왕이면 제네릭 메서드로 만들라. (0) | 2023.02.14 |
[이펙티브자바]item 29.이왕이면 제네릭 타입으로 만들라. (0) | 2023.02.13 |
[이펙티브자바]item 28.배열보다는 리스트를 사용하라. (0) | 2023.02.11 |
댓글