-
아이템28. 배열보다는 리스트를 사용하라Java/이펙티브 자바 2023. 9. 23. 12:28
핵심 정리1 - 배열과 제네릭은 잘 어울리지 않는다.
- 배열은 공변(covariant), 제네릭은 불공변
- 배열은 실체화(reify) 되지만, 제네릭은 실체화 되지 않는다. (소거)
ㆍ제네릭은 컴파일할 때 타입이 사라진다.
- new Generic<타입>[배열] 은 컴파일 할 수 없다.
- 제네릭 소거 : 원소의 타입은 컴파일 타임에만 검사하며 런타임에는 알 수 없다.
public static void main(String[] args) { // 공변 : 같이 변한다. Object[] anything = new String[10]; anything[0] = 1; // 잘못된 동작이지만 컴파일러가 잡지 못한다. - 런타임 에러 // 불공변 : 같이 변하지 않는다. List<String> names = new ArrayList<>(); // List<Object> objects = names; // 컴파일 에러. }
핵심 정리2
- 배열기반은 범용적으로 사용하기 어렵다. - 타입 캐스팅을 써야함.
ㆍ범용적으로 쓸 수 있는 클래스의 타입 형변환 문제 발생 -> 제네릭 사용
완벽 공략 - @SafeVarargs
: 생성자와 메서드의 제네릭 가변인자에 사용할 수 있는 애노테이션
- 제네릭 가변인자는 근본적으로 타입 안전하지 않다. (가변인자가 배열이니까, 제네릭 배열과 같은 문제)
- 가변 인자 (배열)의 내부 데이터가 오염될 가능성이 있다.
- @SafeVarargs를 사용하면 가변 인자에 대한 해당 오염에 대한 경고를 숨길 수 있다.
- 아이템 32. 제네릭과 가변인수를 함께 쓸 때는 신중하라.
public class SafeVaragsExample { // @SafeVarargs // Not actually safe! static void notSafe(List<String>... stringLists) { // List<String>[] 이 가능하지만 전달받은 객체가 오염이 될 수 있다. Object[] array = stringLists; // List<String>... => List[], 그리고 배열은 공변이다. List<Integer> tmpList = List.of(42); array[0] = tmpList; // Semantically invalid, but compiles without warnings String s = stringLists[0].get(0); // ClassCastException at runtime! } // @SafeVarargs static <T> void safe(T... values) { for (T value: values) { System.out.println(value); } } }
'Java > 이펙티브 자바' 카테고리의 다른 글
아이템31. 한정적 와일드카드를 사용해 API 유연성을 높이라 (0) 2023.10.31 아이템29 & 아이템30 (0) 2023.09.28 아이템 27. 비검사 경고를 제거하라 (0) 2023.09.21 아이템26. 로 타입은 사용하지 말라. (0) 2023.09.18 아이템 22 & 아이템 23 & 아이템 24 & 아이템 25 (0) 2023.09.07