가변인수 메서드를 호출하면 가변인수를 담기 위해 배열이 자동으로 하나 만들어진다.
내부에서 사용하는 배열이 클라이언트에게 노출되는 문제점이 있다.
제네릭이나 매개변수화 타입을 포함한 가변 인수 메서드를 호출하면 컴파일러가 경고를 보낼것이다.
매개 변수화된 Vararg 유형으로 인한 힙 오염 가능성으로 경고가 발생한다고 확인 할 수 있다.
제네릭과 가변인수를 같이 사용하면 타입 안정성이 깨진다.
public static void test1(List<String>...stringLists){
List<Integer> intList = List.of(42);
Object[] objects = stringLists;
objects[0] = intList; // 힙오염 발생
String s = stringLists[0].get(0); // ClassCastException;
}
내부에서 List<Integer> 타입을 Object[] 에 넣고 꺼내면 ClassCastException 이 발생한다. 이러한 부분으로 힙 오염도 발생한다.
따라서 가변인수와 제네릭을 사용하면 타입의 안정성을 보장하지 않는다.
하지만 이러한 경우는 실무에서 굉장히 유용하다. Arrays.asList() 와 Collections.addAll() 등이 있다.
@SafeVaragrs 애너테이션
- @SuppressWarnings(”uncheckd”)
- 경고가 발생하면 타입의 안정성을 작성자가 확신하다고 볼 때 애너테이션으로 경고를 숨긴다.
- 가독성이 떨어지고, 진짜 문제를 알려주는 경고마저 숨긴다.
- @SafeVarargs
- 작성자가 그 메서드가 타입 안전함을 보장하는 장치
- 컴파일러가 이 약속을 믿고 이 메서드가 안전하지 않을 수 있다는 경고를 더이상 하지 않는다.
메서드가 안전한지 확신 할 수 있을 때
- 메서드가 varargs 매개변수를 담는 배열에 아무것도 저장하지 않을 때
- varargs 배열의 참조가 밖으로 노출 되지 않을 때
순수하게 인수들을 전달할 때에만 메서드가 안전하다.
제네릭 varargs 매개변수 배열에 다른 메서드가 접근하도록 허용하지 말자
- 자신의 제네릭 매개변수 배열의 참조를 노출하므로 안전하지 않다.
- 힙 오염을 메서드를 호출한 쪽의 콜스택으로 까지 전이하는 결과를 낳는다.
'Book > Effective Java' 카테고리의 다른 글
[Item 34] int 상수 대신 열거 타입을 사용하라 (0) | 2022.09.02 |
---|---|
[Item 33] 타입 안전 이종 컨테이너를 고려하라 (0) | 2022.09.02 |
[Item 31] 한정적 와일드카드를 사용해 API 유연성을 높이라 (0) | 2022.08.31 |
[Item 30] 이왕이면 제네릭 메서드로 만들라 (0) | 2022.08.30 |
[Item 29] 이왕이면 제네릭 타입으로 만들라 (0) | 2022.08.18 |
[Item 28] 배열보다는 리스트를 사용하라 (0) | 2022.08.18 |
[Item 27] 비검사 경고를 제거하라 (0) | 2022.08.06 |
[Item 26] 로 타입(Raw Type)은 사용하지 말라 (0) | 2022.08.05 |