요약
인수 개수가 일정하지 않은 메서드를 정의해야 한다면 가변인수를 사용하라
가변인수 사용은 성능 문제에 영향을 미치므로 신중히 사용하자
가변인수 메서드란?
고정된 매개변수의 수를 받는 것이 아닌 명시한 타입의 인수를 0개 이상으로 가변적으로 인수를 받을 수 있는 메서드이다. 인수 개수가 정해지지 않은 경우에 가변인수는 유용하게 사용할 수 있다.
가변인수 메서드 동작 순서
- 인수의 개수와 길이가 같은 배열을 생성한다.
- 인수들을 배열에 저장한다.
- 배열을 가변인수 메서드에 전달한다.
예시
static int sum(int... args) {
int sum = 0;
for (int arg : args) {
sum += arg;
}
return sum;
}
// sum(1,2,3)은 6을 반환하고, sum()은 0을 반환한다
예외
인수가 무조건 1개 이상이어야 할 때도 있는데, 최솟값을 찾는 메서드가 해당된다. 참고로 인수개수는 런타임에 자동 생성된 배열의 길이로 알 수 있다.
1) 문제되는 코드
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개인 상황을 확인할 수 있지만, 2가지 문제점이 있다.
- 인수가 0개일 때 유효성 검사가 컴파일 타임이 아닌 런타임 실패인 것
- 코드가 지저분한 것
- 매개변수 유효성 검사가 명시적이고, for-each문을 사용하기가 어렵다.
2) 더 나은 코드
static int min(int firstArg, int... remainingArgs) {
int min = firstArg;
for (int remainingArg : remainingArgs) {
if (remainingArg < min) {
min = remainingArg;
}
}
return min;
}
- 첫 번째로는 일반 매개변수(가변인수에서 첫번째 인수)를 받고, 두번째로 가변인수를 받으면 이전의 문제가 사라진 깔끔한 코드를 작성할 수 있다.
성능
가변인수 메서드는 호출될 때마다 배열을 새로 하나 할당하고 초기화하기 때문에 성능에 민감한 상황에서는 걸림돌이 될 수 있다. 만약 가변인수의 유연성이 필요하지만 비용을 감당하기가 어려울 때 사용할 수 있는 방법이 있다.
예시 - 다중정의
해당 메서드 호출의 95%가 인수를 3개 이하로 사용한다고 가정하면, 다음과 같이 메서드 다중정의를 할 수 있다.이 방법은 혹시나 4개 이상의 인수를 받아야할 상황에 도움이 될 수 있다.
예시로 EnumSet이 있는데, EnumSet은 비트필드를 대체하면서 성능까지 유지해야 하므로 이 기법으로 정적 팩터리를 생성하면 열거 타입 집합 생성 비용을 최소화한다.
주의) 가변인수는 메서드 파라미터 마지막에 위치해야한다.
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) { } // 5%만 적용
'Dev Language > EffectiveJava' 카테고리의 다른 글
[EffectiveJava] 리플렉션보다는 인터페이스를 사용하라 (0) | 2025.04.06 |
---|---|
[EffectiveJava] 지역변수의 범위를 최소화하라 (0) | 2025.03.30 |
[EffectiveJava] 다중정의는 신중히 사용하라 (0) | 2025.03.16 |
[EffectiveJava] 적시에 방어적 복사본을 만들라 (0) | 2025.03.09 |
[EffectiveJava] 스트림 병렬화는 주의해서 적용하라 (0) | 2025.03.03 |