가변인수(varargs) : 자바에서 메서드에 임의의 개수의 인수를 전달할 수 있도록 하는 기능. 이를 통해 메서드를 호출할 때 원하는 개수의 인수를 전달할 수 있다. 가변인수는 배열로 처리되며, 메서드 선언 시에 타입 뒤에 세 개의 점(...)을 사용하여 정의한다.
제네릭 : 자바 프로그래밍 언어의 한 기능으로, 타입 매개변수를 사용하여 클래스, 인터페이스, 메서드를 정의하는 방법. 이를 통해 컬렉션 클래스나 제네릭 메서드 등을 작성할 때 특정 타입에 의존하지 않고 일반화된 형태로 구현할 수 있다.
@SafeVarargs : 자바의 애너테이션 중 하나로, 가변인수(varargs) 매개변수를 사용하는 메서드에 붙인다. 이 애너테이션은 컴파일러에게 해당 메서드가 안전하게 사용될 수 있다는 것을 알려준다.
제네릭과 가변인수를 함께 사용할 때 주의점 :
- 가변인수의 타입이 제네릭일 경우에는 @SafeVarargs 애너테이션을 사용해야 한다.
- 제네릭 배열을 생성하는 것은 안전하지 않으므로, 컴파일러 경고가 발생할 수 있다.
- 가변인수의 타입이 제네릭이거나, 가변인수를 포함하는 제네릭 메서드를 오버로드할 경우 혼동을 줄 수 있다.
import java.util.Arrays;
import java.util.List;
public class GenericVarargsExample {
// 주의사항 1: 가변인수의 타입이 제네릭일 경우에는 @SafeVarargs 애너테이션을 사용해야 함
@SafeVarargs
public static <T> List<T> createList(T... elements) {
return Arrays.asList(elements);
}
// 주의사항 2: 제네릭 배열 생성은 안전하지 않음
public static <T> T[] createArray(T... elements) {
// 컴파일러 경고 발생 가능
return elements;
}
// 주의사항 3: 제네릭과 가변인수를 함께 사용한 오버로딩은 혼동을 줄 수 있음
public static void processElements(String... elements) {
System.out.println("Processing Strings...");
for (String element : elements) {
System.out.println(element);
}
}
public static void processElements(Integer... elements) {
System.out.println("Processing Integers...");
for (Integer element : elements) {
System.out.println(element);
}
}
public static void main(String[] args) {
// 예시 1: @SafeVarargs 애너테이션 사용한 제네릭 가변인수 메서드 호출
List<Integer> intList = createList(1, 2, 3, 4, 5);
System.out.println("Integer List: " + intList);
// 예시 2: 제네릭 배열 생성
String[] stringArray = createArray("Hello", "World");
System.out.println("String Array: " + Arrays.toString(stringArray));
// 예시 3: 제네릭과 가변인수를 함께 사용한 오버로딩
processElements("One", "Two", "Three"); // 어떤 메서드가 호출될까?
processElements(1, 2, 3); // 어떤 메서드가 호출될까?
}
}
- createList 메서드에서는 @SafeVarargs 애너테이션을 사용하여 제네릭 가변인수를 안전하게 처리한다.
- createArray 메서드에서는 제네릭 배열 생성으로 인한 컴파일러 경고를 확인할 수 있다.
- processElements 메서드에서는 제네릭과 가변인수를 함께 사용한 오버로딩이 혼동을 줄 수 있음을 보여준다. 호출할 때 어떤 메서드가 호출될지 주의해야 한다.
결론 : 가변인수와 제네릭은 궁합이 좋지 않다. 가변인수 기능은 배열을 노출하여 추상화가 완벽하지 못하고, 배열과 제네릭의 타입 규칙이 서로 다르기 때문이다. 제네릭 varargs 매개변수는 타입 안전하지는 않지만, 허용된다. 메서드에 제네릭 (혹은 매개변수화된)varargs 매개변수를 사용하고자 한다면, 먼저 그 메서드가 타입 안전한지 확인한 다음 @SafeVarargs 애너테이션을 달아 사용하는 데 불편함이 없게끔 하자.
'이펙티브 자바' 카테고리의 다른 글
[이펙티브 자바] 아이템 34. int 상수 대신 열거 타입을 사용하라 (0) | 2024.04.04 |
---|---|
[이펙티브 자바] 아이템 33. 타입 안전 이종 컨테이너를 고려하라 (0) | 2024.04.03 |
[이펙티브 자바] 아이템 31. 한정적 와일드카드를 사용해 API 유연성을 높여라 (0) | 2024.04.01 |
[이펙티브 자바] 아이템 30. 이왕이면 제네릭 메서드로 만들라 (0) | 2024.04.01 |
[이펙티브 자바] 아이템 29. 이왕이면 제네릭 타입으로 만들라 (0) | 2024.03.28 |