가변 인자와 배열 경계
호출마다 인자 개수가 달라지는 메서드는 ... 문법으로 가변 인자를 받을 수 있습니다.
메서드 안에서는 가변 인자가 배열로 보이며 인자가 없으면 길이 0인 배열이 전달됩니다.
가변 인자는 매개변수 목록의 마지막에 하나만 둘 수 있습니다.
배열을 직접 전달하는 호출과 개별 값을 나열하는 호출이 모두 가능해 API가 편해지지만 오버로딩과 섞으면 해석이 복잡해질 수 있습니다.
이 절에서는 가변성의 편의와 호출 계약을 비교합니다.
가변 인자는 메서드 안에서 배열이다
`int...
values는 본문에서 int[]`처럼 길이와 인덱스를 사용합니다.
호출할 때 컴파일러가 필요한 배열을 구성합니다.
인자가 없는 호출도 정상 입력이다
빈 배열을 합계 0이나 빈 결과로 처리할지, 최소 한 개를 요구할지 메서드 계약으로 정해야 합니다.
필요하면 길이를 검사해 예외를 냅니다.
VarargsValues.java는 필수 첫 값 하나만 넘기는 호출, 여러 값을 나열하는 호출, 기존 배열을 넘기는 호출을 나란히 둡니다. 세 호출에서 rest.length가 각각 얼마인지 실행 전에 예측해 보세요.
import java.util.Arrays;
public class VarargsValues {
static int sum(int first, int... rest) {
int total = first;
for (int value : rest) total += value;
return total;
}
public static void main(String[] args) {
System.out.println(sum(10));
System.out.println(sum(10, 20, 30));
int[] extra = {5, 6};
System.out.println(sum(1, extra));
System.out.println(Arrays.toString(extra));
}
}sum(10)처럼 필수 인자만 넘기면 가변 부분 rest에는 길이 0인 배열이 들어옵니다. 이 메서드는 최소 한 값을 요구하도록 first를 분리했으므로 sum() 호출은 컴파일되지 않습니다.
10
60
12
[5, 6]가변 부분 rest는 인자가 없을 때도 null이 아니라 길이 0인 배열입니다.
고정 매개변수 뒤 마지막에 둔다
`format(String pattern, Object...
args)`처럼 필수 입력을 먼저 두고 선택적인 반복 입력을 마지막에 둡니다.
가변 인자 뒤에는 다른 매개변수를 선언할 수 없습니다.
가변 인자는 호출 문법만 유연하게 만들 뿐 내부에서는 배열과 같습니다. 이미 배열이 있는 호출과 값 여러 개를 나열한 호출을 모두 시험하고, sum(1, (int[]) null)처럼 null 배열을 명시적으로 넘기는 특별한 호출을 금지할지도 메서드 계약에서 정합니다.
static void log(String level, Object... values) { }log("INFO");
log("INFO", "user", 42);// static void broken(int... values, String label) { }
// 컴파일 오류: 가변 인자는 마지막 매개변수 하나만 가능// 최소 한 개가 필요해 first를 고정 매개변수로 분리했다.가변 인자는 짧은 호출을 위한 문법이며 최소 개수와 빈 입력의 의미를 메서드 계약에서 따로 정해야 합니다.