가변인수(varargs)
가변인수는 인수 개수가 정해지지 않았을 때 아주 유용하다.
명시한 타입의 인수를 0개 이상 받을 수 있다.
가변인수 메서드 호출시, 인수 개수 길이의 배열에 인수를 담아서 가변인수 메서드에 전달한다. 즉 호출시마다 새로운 배열을 할당하고 초기화한다.
가변인수 간단 예시
다음은 가변인수를 활용한 간단한 예시이다. 인수로 int... args가 들어간다.
// 입력받은 int 인수들의 합을 계산해주는 가변인수 메서드
static int sum(int... args){
int sum = 0;
for(int arg : args)
sum += arg;
return sum;
}
인수가 1개 이상이어야 하는 가변인수 메서드
예를 들어, 최솟값을 찾는 메서드를 생각해보면 인수가 0개 들어오도록 설계하는 것은 좋지 않다.
1. 잘못 구현한 예
인수가 1개 이상이어야 할 때, 애초에 인수 개수가 0개 들어오도록 설계하는 것은 좋지 않다.
// ∨ 아래 코드의 가장 심각한 문제: 인수 0개 넣어 호출하면 "런타임에 실패"함
// ∨ 지저분한 코드
// ∨ args 유효성 검사를 명시적으로 해야 함
static int min(int... args){
if(args.length == 0)
throw new IllegalArgumentException("인수가 1개 이상 필요합니다.");
int min = args[0];
for(int i=1; i< args.length; i++)
if(args[i] < min)
min = args[i];
return min;
}
2. 잘 구현한 예
첫 번째 인수를 아래와 같이 받으면 된다. 그리고 가변인수는 두 번째 인수로 설정하면 된다.
그러면 '인수가 1개 이상이어야 할 때'의 코드가 만족스럽다.
static int min(int firstArg, int... remainingArgs){
int min = firstArg;
for(int arg : remainingArgs)
if(arg < min)
min = arg;
return min;
}
*참고: 자바에 도입된 printf와 리플렉션(Item65)는 가변인수 덕을 톡톡히 보고 있다.
가변인수와 성능
가변인수 메서드는 일단 호출시마다 배열을 새로 하나 할당하고 초기화하기 때문에,
성능에 민감하다면 고민해봐야 하는 부분이다.
만약 메서드 호출의 95%가 인수를 3개 이하로 사용하고 있다면,
차라리 메서드를 오버로딩 하는 것이 좋을 거라고 한다.
인수 개수마다 각각의 오버로딩 메서드로 두자는 것이다 ↓
public void foo() { }
public void foo(int a1) { }
public void foo(int a1, int a2) { }
public void foo(int a1, int a2, int a3) { }
public void foo(int a1, int a2, int a3, int... rest) { }
*참고: EnumSet의 정적 팩터리도 이 기법을 사용해 열거 타입 집합 생성 비용을 최소화한다. EnumSet은 비트 필드(Item36)을 대체하면서 성능까지 유지해야 하므로 아주 적절하게 활용한 예라 할 수 있다.
'JAVA > Effective Java' 카테고리의 다른 글
[이펙티브 자바] 옵셔널 반환은 신중히 하라 ─ 8장:메서드:Item55 (1) | 2023.10.18 |
---|---|
[이펙티브 자바] null이 아닌, 빈 컬렉션이나 배열을 반환하라 ─ 8장:메서드:Item54 (0) | 2023.10.18 |
[이펙티브 자바] 다중정의(오버로딩)는 신중히 사용하라 ─ 8장:메서드:Item52 (1) | 2023.10.17 |
[이펙티브 자바] 메서드 시그니처를 신중하게 설계하라 ─ 8장:메서드:Item51 (0) | 2023.10.17 |
[이펙티브 자바] 적시에 방어적 복사본을 만들라 ─ 8장:메서드:Item50 (1) | 2023.10.17 |