Java 가변 매개변수 (Varargs)
가변 매개변수(Variable Arguments, Varargs)는 메서드가 개수 제한 없이 여러 개의 인자를 받을 수 있도록 지원하는 기능입니다.
이 기능은 Java 5부터 도입되었으며, 매개변수의 개수가 동적으로 변할 수 있는 경우 유용하게 사용할 수 있습니다.
1. 가변 매개변수 문법
가변 매개변수는 ...(세 개의 점) 기호를 사용하여 선언합니다.
public void printNumbers(int... numbers) {
for (int num : numbers) {
System.out.println(num);
}
}
위 코드에서 int... numbers는 개수가 정해지지 않은 int 타입의 배열을 의미합니다.
2. 가변 매개변수 사용 예시
(1) 매개변수 개수 제한 없이 전달 가능
public class VarargsExample {
public static void printNumbers(int... numbers) {
for (int num : numbers) {
System.out.print(num + " ");
}
System.out.println();
}
public static void main(String[] args) {
printNumbers(1);
printNumbers(1, 2, 3, 4, 5);
printNumbers(); // 아무 값도 전달하지 않을 수도 있음
}
}
출력 결과
1
1 2 3 4 5
(아무 출력 없음)
(2) 내부적으로 배열로 처리됨
가변 매개변수는 내부적으로 배열로 처리됩니다. 따라서, 아래 두 코드는 동일하게 동작합니다.
public void printNumbers(int... numbers) { /* 구현부 */ }
public void printNumbers(int[] numbers) { /* 구현부 */ }
하지만 printNumbers(int... numbers)는 호출 시 배열을 명시적으로 만들 필요가 없다는 장점이 있습니다.
printNumbers(1, 2, 3); // 가능 (가변 매개변수)
printNumbers(new int[]{1, 2, 3}); // 가능 (배열)
3. 가변 매개변수와 일반 매개변수 혼용
가변 매개변수는 다른 일반 매개변수와 함께 사용 가능합니다.
하지만, 가변 매개변수는 반드시 마지막 매개변수로 선언해야 합니다.
✅ 올바른 사용 예
public void printInfo(String name, int... scores) {
System.out.print(name + "의 점수: ");
for (int score : scores) {
System.out.print(score + " ");
}
System.out.println();
}
printInfo("홍길동", 90, 85, 88);
printInfo("김철수");
출력 결과
홍길동의 점수: 90 85 88
김철수의 점수:
❌ 잘못된 사용 예 (컴파일 에러 발생)
public void wrongMethod(int... numbers, String name) { }
⛔ 오류: 가변 매개변수는 마지막에 와야 합니다.
4. 메서드 오버로딩과 가변 매개변수
가변 매개변수는 오버로딩할 때 주의해야 합니다.
컴파일러가 가변 매개변수와 일반 매개변수 간의 모호한 호출을 방지하기 위해 명확한 구분이 필요합니다.
✅ 정상적인 오버로딩
public void printValues(int num) {
System.out.println("정수: " + num);
}
public void printValues(int... numbers) {
System.out.println("배열 길이: " + numbers.length);
}
printValues(10); // 첫 번째 메서드 호출
printValues(10, 20); // 두 번째 메서드 호출
출력 결과
정수: 10
배열 길이: 2
하지만, 아래와 같이 printValues(int number, int... numbers)를 추가하면 printValues(10) 호출이 애매해집니다.
public void printValues(int num, int... numbers) { }
이 경우 printValues(10)이 printValues(int num, int... numbers)를 호출할지 printValues(int num)을 호출할지 애매해지므로 컴파일 오류가 발생합니다.
5. 가변 매개변수와 성능 고려
가변 매개변수는 내부적으로 배열을 생성하므로 성능에 영향을 줄 수 있습니다.
특히, 자주 호출되는 메서드에서 불필요하게 가변 매개변수를 사용할 경우 객체 생성 비용이 증가할 수 있습니다.
⚡ 성능 최적화 방법
public void process(int first, int second) {
// 가변 매개변수가 필요 없는 경우
}
public void processVarargs(int first, int... others) {
// 필요할 때만 배열 생성
}
✅ process(1, 2)처럼 정해진 개수를 받을 때는 배열이 생성되지 않아 성능이 좋습니다.
6. 정리
✔ 가변 매개변수(...)는 여러 개의 인자를 받을 수 있도록 지원하는 기능
✔ 내부적으로 배열로 처리되며, 배열을 직접 만들 필요 없이 편리하게 사용할 수 있음
✔ 반드시 메서드의 마지막 매개변수로 선언해야 함
✔ 오버로딩 시 혼동되지 않도록 주의해야 함
✔ 빈번한 호출이 예상되는 경우, 불필요한 객체 생성을 줄이도록 고려해야 함
✅ 실전 활용 예시
문자열을 연결하는 메서드
public static String joinStrings(String delimiter, String... words) {
return String.join(delimiter, words);
}
public static void main(String[] args) {
System.out.println(joinStrings(", ", "Apple", "Banana", "Cherry"));
}
출력 결과
Apple, Banana, Cherry
합계를 구하는 메서드
public static int sum(int... numbers) {
int total = 0;
for (int num : numbers) {
total += num;
}
return total;
}
public static void main(String[] args) {
System.out.println(sum(1, 2, 3, 4, 5)); // 15
}
가변 매개변수를 적절히 활용하면 코드를 더 유연하고 간결하게 만들 수 있습니다.
하지만 과도한 사용은 성능 저하를 초래할 수 있으므로 필요할 때만 사용하는 것이 좋습니다.
가변 매개변수에 클래스 타입 적용
네! 가변 매개변수는 기본 타입(primitive type)뿐만 아니라 클래스 타입도 사용할 수 있습니다.
즉, 가변 매개변수의 타입으로 사용자 정의 클래스, 인터페이스, 제네릭 타입 등을 사용할 수 있습니다.
1. 클래스 타입을 가변 매개변수로 사용하는 예제
아래 예제에서는 Product라는 클래스를 만들고, 여러 개의 Product 객체를 가변 매개변수로 전달하는 메서드를 구현합니다.
✅ Product 클래스
class Product {
private String name;
private int price;
public Product(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "상품명: " + name + ", 가격: " + price + "원";
}
}
✅ 가변 매개변수를 활용한 메서드
public class VarargsExample {
public static void printProducts(Product... products) {
System.out.println("상품 목록:");
for (Product product : products) {
System.out.println(product);
}
}
public static void main(String[] args) {
Product p1 = new Product("노트북", 1500000);
Product p2 = new Product("스마트폰", 1000000);
Product p3 = new Product("태블릿", 800000);
printProducts(p1, p2, p3);
}
}
✅ 실행 결과
상품 목록:
상품명: 노트북, 가격: 1500000원
상품명: 스마트폰, 가격: 1000000원
상품명: 태블릿, 가격: 800000원
2. 가변 매개변수에 객체 배열 전달 가능
가변 매개변수는 내부적으로 배열로 처리되므로, 객체 배열을 전달할 수도 있습니다.
Product[] products = { new Product("키보드", 50000), new Product("마우스", 30000) };
printProducts(products);
위 코드에서 products 배열을 printProducts(products)에 전달해도 정상적으로 동작합니다.
3. 제네릭 클래스와 가변 매개변수
제네릭 타입도 가변 매개변수로 사용할 수 있습니다.
class Box<T> {
private T item;
public Box(T item) {
this.item = item;
}
@Override
public String toString() {
return "Box[" + item.toString() + "]";
}
}
public class VarargsGenericExample {
public static <T> void printBoxes(Box<T>... boxes) {
for (Box<T> box : boxes) {
System.out.println(box);
}
}
public static void main(String[] args) {
Box<String> box1 = new Box<>("사과");
Box<Integer> box2 = new Box<>(100);
Box<Double> box3 = new Box<>(99.99);
printBoxes(box1, box2, box3);
}
}
✅ 실행 결과
Box[사과]
Box[100]
Box[99.99]
4. 가변 매개변수 사용 시 주의점
- null 값을 허용할지 여부를 고려해야 함
- printProducts(null); // NullPointerException 발생 가능
- 메서드 오버로딩 시 가변 매개변수는 모호성을 초래할 수 있음
- public void print(String str) { } public void print(String... strs) { } // 충돌 가능
- 성능 고려
- 가변 매개변수는 호출될 때마다 배열을 생성하므로, 성능이 중요한 코드에서는 일반 배열이나 List<T> 사용을 고려할 것.
🔹 결론
✔ 가변 매개변수는 기본 타입뿐만 아니라 클래스 타입도 사용 가능
✔ 배열처럼 활용할 수 있으며, 객체 배열도 전달할 수 있음
✔ 제네릭 타입도 가변 매개변수로 사용할 수 있음
✔ 성능과 null 처리에 주의할 필요가 있음
'개발 > 자바' 카테고리의 다른 글
| Java instanceof 활용 및 문제점 (0) | 2025.02.19 |
|---|---|
| Java 제네릭(Generic) 클래스란? (0) | 2025.02.19 |
| LocalDate 주요 메서드 정리 (0) | 2025.02.19 |
| SimpleDateFormat Thread-Safe 문제 (0) | 2025.02.19 |
| Java 7 이하에서 날짜 및 시간 관련 클래스 (0) | 2025.02.19 |