Item53. 가변인수는 신중히 사용하라!
가변인수
- 가변인수(varargs) 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있다.
- 가변인수 메서드를 호출하면, 가장 먼저 인수의 개수와 길이가 같은 배열을 만들고, 인수들을 배열에 저장하여 가변인수 메서드에 전달한다.
간단한 활용 예시
1
2
3
4
5
6
7
public int sum(int... args) {
int sum = 0;
for (int arg : args) {
sum += arg;
}
return sum;
}
인수를 받아야 할 때
잘못 사용한 예
1
2
3
4
5
6
7
8
9
10
11
static int sum(int... numbers) {
if (numbers.lenght == 0) {
throw new IllegalArgumentException("인수가 1개 이상 필요합니다.");
}
int sum = 0;
for (int number : numers) {
sum += number;
}
return sum;
}
1
2
3
sum(1); // 1
sum(1, 7); // 8
sum(); // error
- 이렇게 오류를 던지도록 하는 방식은 좋지 않다.
- 컴파일 타임이 아닌 런타임에 실패한다.
- 코드가 지저분해진다.
올바르게 사용한 예
1
2
3
4
5
6
7
8
static int sum(int firstNumber, int... numbers) {
int sum = firstNumber;
for (int number : numers) {
sum += number;
}
return sum;
}
- 가변인수 매개변수를 하나만 받는 것보다 위의 코드처럼 매개변수를 2개 받도록 하면 된다.
- 사용해야 하는 필요한 매개변수는 평범하게 받고, 가변인수를 두 번째 매개변수로 받는다.
주의할 점
성능에 민감한 상황이라면 가변인수가 걸림돌이 될 수 있다.
- 가변인수 메서드는 호출될 때마다 배열을 새로 하나 할당 및 초기화한다.
성능 저하를 최소화하기 위해 메서드 오버로딩을 사용할 수 있다.
1 2 3 4 5
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... args) {}
- 인수 3개 이하가 95%의 사용량을 차지하고, 나머지가 5%를 차지한다고 가정해보자.
- 다중정의 메서드를 통해 가변인수를 사용하게 되는 매개변수를 4개 이상 받는 경우는 5% 밖에 되지 않는다.
- 이러한 방법을 사용해 유연성을 지키면서 성능을 최적화할 수 있다.
- 이러한 전략을 사용한 대표적인 예는 EnumSet의 정적 팩터리다. 이 기법을 통해 열거 타입 집합 생성 비용을 최소화한다.
- 인수 3개 이하가 95%의 사용량을 차지하고, 나머지가 5%를 차지한다고 가정해보자.
핵심 정리
- 인수 개수가 일정하지 않은 메서드를 정의해야 한다면 가변인수가 반드시 필요하다.
- 메서드를 정의할 때 필수 매개변수는 가변인수 앞에 두고, 가변인수를 사용할 때는 성능 문제를 고려해 사용하자.
Comments powered by Disqus.