JAVA/이펙티브 자바

32. 제네릭과 가변인수를 함께 쓸 때는 신중하라

간펴니 2023. 7. 16. 21:45
728x90

가변인수 메서드와 제네릭은 잘 어우러지지 않는다.

 

가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어진다.

 

그런데 내부로 감춰야 했을 이 배열을 그만 클라이언트에 노출하는 문제가 생겼다.

 

그 결과 제네릭이나 매개변수화 타입이 포홤되면 알기 어려운 컴파일 경고가 발생한다.

 

메서드를 선언할 때 실체화 불가 타입으로 매개변수를 선언하면 컴파일러가 경고를 보낸다.

 

가변인수 메서드를 호출할 때도 가변 매개변수가 실체화 불가 타입으로 추론되면 경고가 발생하고,

 

이 매개변수화 타입의 변수가 타입이 다른 객체를 참조하면 힙 오염이 발생한다.

 

이런 상황에서는 컴파일러가 자동 생성한 형변환이 실패할 수 있으니, 제네릭 타입 시스템이 약속한 타입 안정성의 근간이 흔들려버린다.

 

 

메서드에 제네릭 가변인수를 사용하고자 한다면 그 메서드가 타입 안정한지 확인한 다음 @SafeVarags 애너테이션을 달아 사용하는데 불편함이 없게끔 해야한다.

 

이 아이템은 제네릭과 가변인수를 함께 사용할 때 주의할 점과, 해결책을 설명해준다.

 

하지만 지금까지의 내 경험에서 제네릭과 가변인수를 함께 사용해본 적이 없다.

 

주의점과 해결책을 짧게 요약해서 인지하고 있고, 후에 사용할 일이 있게되면 해당 포스팅을 자세하게 작성해보도록 하겠다.

 

 


질문 1: 제네릭과 가변인수를 함께 사용할 때 주의해야 할 점은?                                                                                                                

 

타입 안정성 경고가 발생할 수 있다. 이는 가변인수 배열이 실제로는 제네릭이 아닌 배열이기 때문이다.

 

경고는 @SafeVarags 어노테이션으로 억제할 수 있지만, 해당 메서드의 가변인수가 타입 안정성이 보장되는지 확실히 확인한 후 사용해야 한다.

 

타입불일치가 발생할 수 있으며, 이런 경우 배열을 명시적으로 생성하여 전달하거나 Array.asList() 등을 이용하여 리스트로 전달하는 방법 등을 사용할 수 있다.

 

 

 

 

질문 2: @SafeVarargs 어노테이션은 어떤 역할을 하는가?                                                                                                                     

 

가변인수는 매개변수를 배열로 변환하고 이 배열과 관련된 타입 안정성을 보장하지 않기 때문에 경고메시지가 발생할 수 있다.

 

해당 어노테이션은 이 경고를 억제하지만, 적절히 사용하지 않으면 컴파일 또는 런타임 에러를 발생시킬 수 있다.

 

 

 

 

728x90