Notice
Recent Posts
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- basic data-structure
- Queue
- Adv. recursive function
- 선형자료구조
- 기본자료구조
- Simple Brute-Force Algorithm
- 동적계획법
- 깊이우선탐색
- 완전탐색
- binary search
- 고급정렬
- 이진탐색
- 스택
- 매개 변수 탐색
- Divide and Conquer
- 내돈후기
- 힙
- Advanced Sort
- 정렬
- 간단한 완전탐색
- dfs
- Sort
- 알고리즘잡스
- 개념
- parametric search
- 큐
- 우선순위 큐
- heap
- hint
- Stack
- Today
- Total
루시와 프로그래밍 이야기
ITEM32. 제네릭과 가변인수를 함께 쓸 때는 신중하라 본문
※가변인수란? https://sleepyeyes.tistory.com/29
JDK1.5부터 매개변수의 개수를 동적으로 지정해 줄 수 있게 되었는데 이 기능을 가변인자(variable argument)라고 한다.
가변인자는 내부적으로 배열을 생성해서 사용한다!
가변인수 메서드
- 가변인수(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
- 메서드 작성자가 이 메서드가 '타입안전함'을 보장하는 장치.
- 메서드가 안전한 게 확실하지 않다면 절대 어노테이션을 달아서는 안된다.
- 매개변수 배열이 순수하게 '인수들을 전달하는 일'만 한다면 그 메서드는 안전하다.
제네릭 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 어노테이션도 달아야한다.
- 규칙 : 제네릭이나 매개변수화 타입의 varargs 매개변수를 받는 모든 메서드에 @SafeVarargs를 달아라.
- 그래야 사용자를 헷갈리게 하는 컴파일러 경고를 없앨 수 있다.
- 이 말은 안전하지않은 varargs 메서드는 절대 작성해서는 안된다는 뜻이기도 하다.
- 재정의할 수 없는 메서드에만 달아야 한다. 재정의할때 안전을 보장할 수 없기 때문이다.
정리
- 가변인수와 제네릭은 궁합이 좋지 않다.
- 가변인수 기능은 배열을 노출하여 추상화가 완벽하지 못하고,
- 배열과 제네릭의 타입 규칙이 서로 다르기 때문이다.
- 제네릭 varargs 매개변수는 타입 안전하지는 않지만, 허용된다.
- 메서드에 제네릭 가변인수변수를 사용하고자 한다면 먼저 그 메서드가 타입안전인지 확인한 다음 @SafeVarargs를 달아라.
'스터디 > 이펙티브 자바' 카테고리의 다른 글
ITEM42 익명 클래스보다는 람다를 사용하라 (0) | 2022.11.18 |
---|---|
ITEM33. 타입 안전 이종 컨테이너를 고려하라 (0) | 2022.10.13 |
ITEM31. 한정적 와일드카드를 사용해 API 유연성을 높이라 (0) | 2022.10.13 |
ITEM30. 이왕이면 제네릭 메서드로 만들라 (0) | 2022.10.13 |
ITEM29. 이왕이면 제네릭 타입으로 만들라 (1) | 2022.10.12 |
Comments