
자바 varargs는 인자 개수가 매번 달라지는 메서드를 더 편하게 호출하게 해 주는 문법입니다. `String… values`처럼 쓰면 호출하는 쪽에서는 여러 값을 쉼표로 넘길 수 있습니다.
핵심은 varargs가 편한 호출 문법을 제공하지만 메서드 내부에서는 배열처럼 다뤄진다는 점입니다. 이 글은 Java 공식 튜토리얼과 JLS 기준으로 언제 편하고 언제 조심해야 하는지 정리합니다.

자바 varargs를 먼저 한 줄로 정리하면
varargs는 메서드가 같은 타입의 인자를 0개 이상 받을 수 있게 하는 문법입니다. 선언할 때는 `…`을 쓰고, 메서드 내부에서는 배열처럼 다룹니다.
static void printAll(String... values) {
for (String value : values) {
System.out.println(value);
}
}
printAll("A", "B", "C");호출하는 쪽에서는 인자를 여러 개 넘기는 것처럼 보이지만, 메서드 안의 `values`는 `String[]`처럼 사용할 수 있습니다.
varargs는 마지막 매개변수에만 쓸 수 있다
가변 인자는 어디까지가 varargs에 들어가는 값인지 구분해야 하므로 매개변수 목록의 마지막에만 둘 수 있습니다.
static void log(String level, String... messages) {
for (String message : messages) {
System.out.println("[" + level + "] " + message);
}
}배열을 직접 넘길 수도 있다
varargs는 내부적으로 배열처럼 다뤄지므로, 호출할 때 이미 가진 배열을 넘길 수도 있습니다.
String[] names = {"kim", "lee"};
printAll(names);이 특성 때문에 varargs는 편하지만, 배열을 받는 API와 거의 같은 경계에 있다는 점을 기억해야 합니다.
언제 편할까
- 로그 메시지처럼 인자 개수가 자연스럽게 달라질 때
- 테스트 helper에서 입력값을 간단히 나열하고 싶을 때
- 문자열 join, validation rule 목록처럼 같은 종류의 값을 여러 개 받을 때
- 호출부의 가독성이 배열 생성보다 중요할 때
오버로딩과 만나면 헷갈릴 수 있다
varargs 메서드를 오버로딩하면 컴파일러가 어떤 메서드를 골라야 할지 애매해지는 상황이 생길 수 있습니다. 특히 고정 인자 메서드와 가변 인자 메서드가 비슷하면 호출부가 읽기 어려워집니다.
static void send(String value) {}
static void send(String... values) {}
send("hello"); // 읽는 사람이 어떤 의도인지 헷갈릴 수 있음컴파일이 되더라도 API 사용자 입장에서 의미가 모호하면 좋은 설계라고 보기 어렵습니다.
generic varargs 경고는 왜 나올까
generic과 varargs를 함께 쓰면 non-reifiable type과 배열이 만나는 지점에서 경고가 생길 수 있습니다. 단순 입문 코드에서는 자주 마주치지 않지만, 라이브러리 API를 만들 때는 가볍게 넘기면 안 됩니다.
@SafeVarargs
static <T> void printLists(List<T>... lists) {
for (List<T> list : lists) {
System.out.println(list);
}
}`@SafeVarargs`는 정말 안전한 구현일 때만 붙여야 합니다. 경고를 숨기기 위한 장식으로 쓰면 나중에 타입 안정성 문제를 놓칠 수 있습니다.
실무 체크리스트
- 인자들이 모두 같은 의미의 반복 값인지 확인한다
- 인자가 0개일 때 동작이 자연스러운지 정한다
- 배열을 받는 메서드가 더 명확한지 비교한다
- 오버로딩으로 호출 의미가 흐려지지 않는지 본다
- generic varargs 경고를 무시하지 않는다
정리
자바 varargs는 호출부를 간단하게 만드는 좋은 문법입니다. 하지만 API 경계에서는 오버로딩, 배열과의 관계, generic 경고까지 함께 봐야 안전하게 쓸 수 있습니다.
Java 문법 흐름은 자바 enum은 상수 모음보다 더 강하다, 자바 람다에서 effectively final은 왜 필요할까, 자바 제네릭 와일드카드 extends super 차이와 함께 보면 좋습니다. 외부 기준은 Oracle Java Tutorial – Arbitrary Number of Arguments, Java Language Specification 8.4.1 – Formal Parameters, Oracle Java Tutorial – Non-Reifiable Varargs Type를 확인했습니다.