가변인수 메서드와 제네릭은 잘 어우러지지 않는다.
가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어진다.
그런데 내부로 감춰야 했을 이 배열을 그만 클라이언트에 노출하는 문제가 생겼다.
그 결과 제네릭이나 매개변수화 타입이 포홤되면 알기 어려운 컴파일 경고가 발생한다.
메서드를 선언할 때 실체화 불가 타입으로 매개변수를 선언하면 컴파일러가 경고를 보낸다.
가변인수 메서드를 호출할 때도 가변 매개변수가 실체화 불가 타입으로 추론되면 경고가 발생하고,
이 매개변수화 타입의 변수가 타입이 다른 객체를 참조하면 힙 오염이 발생한다.
이런 상황에서는 컴파일러가 자동 생성한 형변환이 실패할 수 있으니, 제네릭 타입 시스템이 약속한 타입 안정성의 근간이 흔들려버린다.
메서드에 제네릭 가변인수를 사용하고자 한다면 그 메서드가 타입 안정한지 확인한 다음 @SafeVarags 애너테이션을 달아 사용하는데 불편함이 없게끔 해야한다.
이 아이템은 제네릭과 가변인수를 함께 사용할 때 주의할 점과, 해결책을 설명해준다.
하지만 지금까지의 내 경험에서 제네릭과 가변인수를 함께 사용해본 적이 없다.
주의점과 해결책을 짧게 요약해서 인지하고 있고, 후에 사용할 일이 있게되면 해당 포스팅을 자세하게 작성해보도록 하겠다.
질문 1: 제네릭과 가변인수를 함께 사용할 때 주의해야 할 점은?
타입 안정성 경고가 발생할 수 있다. 이는 가변인수 배열이 실제로는 제네릭이 아닌 배열이기 때문이다.
경고는 @SafeVarags 어노테이션으로 억제할 수 있지만, 해당 메서드의 가변인수가 타입 안정성이 보장되는지 확실히 확인한 후 사용해야 한다.
타입불일치가 발생할 수 있으며, 이런 경우 배열을 명시적으로 생성하여 전달하거나 Array.asList() 등을 이용하여 리스트로 전달하는 방법 등을 사용할 수 있다.
질문 2: @SafeVarargs 어노테이션은 어떤 역할을 하는가?
가변인수는 매개변수를 배열로 변환하고 이 배열과 관련된 타입 안정성을 보장하지 않기 때문에 경고메시지가 발생할 수 있다.
해당 어노테이션은 이 경고를 억제하지만, 적절히 사용하지 않으면 컴파일 또는 런타임 에러를 발생시킬 수 있다.
'JAVA > 이펙티브 자바' 카테고리의 다른 글
34. int 상수 대신 열거 타입을 사용하라 (0) | 2023.07.18 |
---|---|
33. 타입 안정 이종 컨테이너를 고려하라 (0) | 2023.07.16 |
31. 한정적 와일드카드를 사용해 API 유연성을 높이라 (0) | 2023.07.16 |
29,30. 이왕이면 제네릭 타입으로 만들라 (0) | 2023.07.16 |
28. 배열보다는 리스트를 사용하라 (0) | 2023.07.16 |