1. 가변인수(varargs)
- 가변인수는 말 그대로 인수가 가변적으로 들어올 때 사용할 수 있는 문법으로 명시한 타입의 인수를 0개 이상 받을 수 있습니다.
public class Test {
public static int sum(int... args) {
int sum = 0;
for(int argument : args) {
sum += argument;
}
return sum;
}
}
- 이때 가변인수로 정의된 메서드를 호출하면 받은 인수의 개수와 동일한 길이를 가진 배열을 생성하고 받은 인수를 해당 배열에 넣는 작업을 선행합니다.
- 따라서 위와 같은 for loop이 가능합니다.
2. 최소 1개의 인자를 받아야 하는 가변인수
- 최소 최대값을 찾아야 하는 메서드를 생각해 봅시다.
- 최소 최대값을 찾아야 하는 메서드의 특성 상 반드시 하나의 매개변수는 들어와야 합니다. 하지만 가변인자는 0개 이상을 받을 수 있기 때문에 다음과 같이 구현해볼 수 있습니다.
public class Test {
public static int min(int... args) {
if(args.length == 0) {
throw new IllegalArgumentException("인수가 1개 이상 필요합니다.");
}
int min = args[0];
for(int argument : args) {
min = Math.min(argument, min);
}
return min;
}
}
- 해당 구현 방식에는 문제가 존재합니다.
- 먼저 코드가 전체적으로 깔끔하지 않습니다. 0개 이상을 받을 수 있기 때문에 어떤 인자도 받지 않았을 때의 예외 처리를 해주어야 하기 때문입니다.
- 또한 해당 코드를 실행하여 실제로 어떠한 인수도 주지 않을시에 컴파일타임이 아닌 런타임에 문제가 발생한다는 것입니다.
- 또한 가변인수에 대한 유효성 검사를 명시적으로 해야 하고 min의 값을 Integer.MAX_VALUE로 초기화하지 않고서는 for-each문도 사용할 수 없습니다.
- 다행히도 다음과 같이 구현하면 위의 문제를 모두 해결할 수 있습니다.
public static int min(int first, int... args) {
int min = first;
for(int argument : args) {
min = Math.min(min, argument);
}
return min;
}
- 첫 번째에 평범한 인수를 받고 두번째에 가변인수를 받아주면 최소 하나의 인수를 받아야 한다는 조건이 성립되며 컴파일 시에 확인도 가능합니다.
3. 가변인수와 성능
- 가변인수는 몇개의 인수가 들어올지 예측할 수 없는 상황에는 적절한 방법이 될 수 있습니다. 하지만 가변인수가 메서드에 인자를 넘기는 방식 때문에 문제가 발생합니다.
- 가변인수 메서드는 호출될 때 마다 배열을 만들어 초기화하기 때문에 배열을 만드는 비용이 클 경우 호출될 때 마다 많은 자원이 소모될 수 있습니다. 하지만 다음과 같은 방법을 통해 가변인수의 유연함을 얻을 수 있습니다.
public void foo(){}
public void foo(int arg1){}
public void foo(int arg1, int arg2){}
public void foo(int arg1, int arg2, int arg3){}
public void foo(int arg1, int arg2, int arg3, int... restArgs){}