개발/자바

Java 5 가변 매개변수 (Varargs)

피터JK 2025. 2. 19. 15:20
728x90

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. 가변 매개변수 사용 시 주의점

  1. null 값을 허용할지 여부를 고려해야 함
  2. printProducts(null); // NullPointerException 발생 가능
  3. 메서드 오버로딩 시 가변 매개변수는 모호성을 초래할 수 있음
  4. public void print(String str) { } public void print(String... strs) { } // 충돌 가능
  5. 성능 고려
    • 가변 매개변수는 호출될 때마다 배열을 생성하므로, 성능이 중요한 코드에서는 일반 배열이나 List<T> 사용을 고려할 것.

🔹 결론

가변 매개변수는 기본 타입뿐만 아니라 클래스 타입도 사용 가능
배열처럼 활용할 수 있으며, 객체 배열도 전달할 수 있음
제네릭 타입도 가변 매개변수로 사용할 수 있음
성능과 null 처리에 주의할 필요가 있음 

728x90