Search
Duplicate

Java - 가변 인수(Variable Arguments)

글감
Java
작성자
작성 일자
2024/02/08 06:43
상태
완료
공개여부
공개
Date
생성자
작업자

가변 인수

가변 인수(varargs, Variable Arguments)란 매개변수로 들어오는 값의 개수와 상관없이 동적으로 인수를 받을 수 있게 해주는 문법을 지칭한다.
print("홍길동"); print("홍길동", "이순신"); print("홍길동", "이순신", "유성룡"); print("홍길동", "이순신", "유성룡", "강감찬"); print("홍길동", "이순신", "유성룡", "강감찬", "이도");
Java
복사
이와 같이 매개변수로 들어오는 값들의 개수가 일정하지 않은 메서드가 있다면, 이 메서드를 구성하는 방법으로 메서드 오버로딩(overloading)이 있을 것이다. 하지만 매개변수의 개수가 일정치 않기 때문에 모든 경우를 만들어두어야 해서 비효율적이다.
이러한 상황에서 가변 인자(varargs)를 사용하면, 파라미터들을 통째로 배열로 받아 처리하기 때문에 동적으로 매개변수를 받을 수 있게 된다.
아래처럼 자바의 printf 메서드도 가변 인자를 활용하여 구성되어 있다.
printf(String format, Object... args)
Java
복사
자바 printf 메서드 시그니처

가변 인수 사용법

가변 인수를 사용하려면 메서드의 파라미터 부분에 타입… 매개변수명의 형태로 받으면 된다. 받는 파라미터들은 모아서 컴파일 시 배열로 처리되는데, 배열의 인자 개수는 제한이 없지만 배열 자료형은 매개변수의 타입으로 명시된 것을 따라간다는 것을 명심해야한다.
public static void main(String[] args) { print("홍길동"); print("홍길동", "이순신"); print("홍길동", "이순신", "유성룡"); print("홍길동", "이순신", "유성룡", "강감찬"); print("홍길동", "이순신", "유성룡", "강감찬", "이도"); } public static void print(String... str) { // 가변 인수인 str 매개변수는 String[] 배열 타입으로 받아들인다. for(String s : str) { System.out.print(s + ", "); } }
Java
복사
만약 메서드에서 매개변수로 가변 인수 뿐만 아니라 다른 파라미터들도 받고 싶다면, 받아야 하는 파라미터들을 모두 적은 후 맨 뒤에 가변 인수를 적어주어야 한다.

가변 인수 주의점

1.
가변 인수를 사용하면 성능이 떨어진다.
가변 인수 메서드는 호출될 때마다 배열을 새로 할당하고 초기화하기 때문에 성능이 저하된다. 가변 인수를 꼭 써야하는 상황이라면 아래처럼 유연적인 오버로딩으로 처리하는 것이 권장된다.
class Printer { public void print(int a1) { } public void print(int a1, int a2) { } public void print(int a1, int a2, int a3) { } public void print(int a1, int a2, int a3, int... rest) { } }
Java
복사
2.
가변 인수 자체를 오버로딩할 수 없다.
하나의 클래스 내에서 가변인자를 사용한 메서드를 오버로딩하면, 컴파일러가 어떤 메서드를 사용해야 하는지 구분하지 못해 에러가 발생한다.
class Printer { public void print(String c, String... str) { System.out.println("첫번째 메서드"); System.out.println("rest parameters : " + Arrays.toString(str)); } public void print(String... str) { System.out.println("두번째 메서드"); } } public class Main2 { public static void main(String[] args) { Printer p = new Printer(); // 이 메서드는 첫번째 메서드에도 두번째 메서드에서도 실행이 가능하기 때문에 컴파일러가 햇깔려 오류를 발생하게 된다. p.print("-", "1", "2", "3"); } }
Java
복사
3.
배열 타입 매개변수와 혼용할 수 없다.
가변 인자는 내부적으로 배열을 생성해서 사용하는 것이므로, 아래와 같이 배열 타입의 매개변수와 동시에 정의해 사용하는게 불가능하다.
class Printer { public void print(String... str) { System.out.println("첫번째 메서드"); } public void print(String[] str) { System.out.println("두번째 메서드"); } }
Java
복사
4.
제네릭 타입과 함께 쓸 때는 신중히 사용해야한다.
아래와 같이 제네릭 타입을 노출하거나 해당 타입의 배열을 만들어 반환값으로 사용하면, 힙 오염이 발생하거나 런타임에 에러가 발생할 수 있다.
class Printer { // 제네릭 타입으로 받는 가변 인수 public <T> T[] toArray(T... args) { return args; // 가변 인자들을 문제없이 담기 위해 어떤 타입도 담을 수 있는 가장 상위 타입인 Object 배열을 만들어 반환 } public <T> T[] pick(T a, T b, T c) { T[] arr = toArray(a, b, c); // Object[] 타입 배열로 리턴된다. return arr; } } public class Main { public static void main(String[] args) { Printer p =new Printer(); // 제네릭 메서드에 String 타입으로 전달 String[] s = p.pick("1","2","3"); // ! ERROR - Object[] 타입을 String[] 타입으로 다운캐스팅이 불가능하다. } }
Java
복사