0개 이상의 유동적인 개수의 인수를 허용하는 인수
→ 가변 인수 메소드가 호출 되면 가변 인수의 개수와 같은 길이의 배열을 만들고 인수들을 저장하여 가변 인수 메소드에 건내준다.
static int sum(int... args) {
int sum = 0;
for (int arg : args)
sum += arg;
return sum;
}
위는 가변인수를 받아 합을 반환하는 메소드인데, 가변 인수의 개수가 0도 허용된다.
그렇다면 아래와 같이 0에 대한 예외를 다뤄주면 되지 않을까?
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;
}
이 방식에도 문제가 있다. 인수가 0개인 문제가 컴파일 시점이 아닌 런타임 시점에 발생한다는 것이다.
또한, 유효성 검사를 명시해야하고, min의 초기값을 Integer.MAX_VALUE로 설정하지 않고는 보다 명료한 for-Each 문을 사용할 수 없다.
다행이 아래와 같은 방법으로 해결할 수 있다.
static int min(int firstArg, int... remainingArgs) {
int min = firstArg;
for (int arg : remainingArgs)
if (arg < min)
min = arg;
return min;
}
평범한 매개변수 1개, 가변인수 1개를 받게하면 문제가 사라진다. 평범한 매개변수 1개를 통해 로직을 위한 값이 1개 이상임을 보장할 수 있고 있고, 런타임 에러도 발생하지 않는다. 만약 해당 메소드를 호출하는 곳에서 값이 0개 미만이라면 에러는 런타임이 아닌 컴파일 시점에서 발생할 것이다.
또한, 가변 인수는 호출 될 때 마다 새로운 배열을 생성하고 초기화 하기 때문에 성능적인 단점을 가진다.
만약, 위의 성능 단점을 안고 가기 싫지만 가변 인수의 유연성을 얻고 싶다면 아래와 같은 구조를 적용해보자.
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) { }
만약, 인자가 3개 이하인 경우가 95%라면 해당 메소드를 사용할 때 배열을 새로 생성하는 경우는 5%밖에 없다. 이렇게 인자 개수의 비율을 고려하면서 해당 구조를 적용해야한다.