본문 바로가기
IT 개인 공부/Java

[Java] 가변인자(Varargs)

by Libi 2021. 8. 16.
반응형

Java에서 오버로딩(Overloading)이란 개념이 존재한다.

오버로딩은 같은 이름의 메서드를 매개변수의 타입과 개수를 다르게 정의하여 다양한 메서드를 구현하는 것을 의미한다.

만약 Varargs 클래스에서 String 타입의 매개변수를 1, 2, 3개씩 가지는 print() 메서드를 오버로딩한다고 해보자. 아마 다음과 같이 구현할 것이다.

class Varargs {
	
	public void print(String s1) {
		System.out.println(s1);
	}
	
	public void print(String s1, String s2) {
		System.out.println(s1 + " " + s2);
	}
	
	public void print(String s1, String s2, String s3) {
		System.out.println(s1 + " " + s2 + " " + s3);
	}
}

 

하지만 이 방법은 추가적으로 4, 5개의 매개변수를 가지는 print() 메서드를 구현하려면 일일이 매개변수를 작성해야 하는 번거로움이 발생하게 된다.

public void print(String s1, String s2, String s3, String s4) {
	System.out.println(s1 + " " + s2 + " " + s3 + " " + s4);
}

public void print(String s1, String s2, String s3, String s4, String s5) {
	System.out.println(s1 + " " + s2 + " " + s3 + " " + s4 + " " + s5);
}

 

근데 메서드를 살펴보면 같은 타입의 매개변수가 반복되는것을 알 수 있다. 따라서 우리는 동일한 타입의 데이터를 관리해주는 배열이나 리스트 같은 자료구조를 사용하면 코드를 단순화시킬 수 있다.

import java.util.Arrays;
import java.util.List;

class Varargs {
	
	public void print(String[] str) {
		System.out.print("String Array : ");
		for (String s : str) System.out.print(s + " ");
		System.out.println();
	}
	
	public void print(List<String> str) {
		System.out.print("String List : ");
		for (String s : str) System.out.print(s + " ");
		System.out.println();
	}
}

public class Main {

	public static void main(String[] args) {
		Varargs varargs = new Varargs();
		varargs.print(new String[] {"A", "B", "C"});
		varargs.print(new String[] {"A", "B", "C", "D"});
		varargs.print(Arrays.asList("A", "B", "C"));
		varargs.print(Arrays.asList("A", "B", "C", "D"));
	}
}

실행결과를 보면 매개변수가 n 개여도 원하는 결과가 출력되는 것을 확인할 수 있다.

 

그런데 이 방법은 배열이나 리스트를 만들어줘야 하는 번거로움이 조금 존재한다.

나는 딱히 번거롭지는 않지만 Java 진영에서는 이러한 번거로움을 개선하기 위해서 Java 1.5부터 매개변수의 개수를 동적으로 지정할 수 있는 가변인자(Varargs)라는 문법을 제공한다. 

가변인자는 다음과 같이 '...'을 사용하여 표현한다. 

매개변수 타입 뒤에 ...을 붙여서 사용
public void print(String...str) {
       //do something
}

 

문법을 보면 알겠지만 당연히 동일한 타입의 매개변수에 적용이 가능하다. 가변인자를 사용하면 위의 코드를 다음과 같이 조금 더 개선시킬 수 있다.

class Varargs {
	
	public void print(String...str) {
		System.out.print("가변인자 : ");
		for (String s : str) System.out.print(s + " ");
		System.out.println();
	}
}

public class Main {

	public static void main(String[] args) {
		Varargs varargs = new Varargs();
		varargs.print("A", "B", "C");
		varargs.print("A", "B", "C", "D");
	}
}

 

마지막으로 가변인자를 사용할 때 주의해야 할 점을 알아보자.

첫 번째로 가변인자는 내부적으로 배열을 생성하여 동작하기 때문에 배열 형식을 제외한 형식은 매개변수로 받을 수 없다.

varargs.print("A", "B", "C");
varargs.print(new String[] {"A", "B", "C"});
varargs.print(Arrays.asList("A", "B", "C")); //컴파일 오류

 

두 번째로 메서드에 가변인자 외에도 다른 매개변수가 존재한다면 가변인자는 항상 마지막에 위치해야 한다.

이유를 찾아보니 가변인자를 어디에나 위치시킬 수 있다면 불필요하게 복잡해지기 때문에 단순화시켜서 마지막에 위치하도록 정한 규칙?같은 것이라고 한다.

public void print(String s, String...str) {
	//do something
}

//컴파일 에러
public void print(String...str, String s) {
	//do something
}

 

마지막으로 가변인자를 사용한 메서드는 같은 타입의 매개변수를 가지는 메서드를 오버로딩해서는 안된다.

public void print(String...str) {
	//do something
}

public void print(String s1, String...str) {
	//do something
}
    
varargs.print("A", "B", "C");//컴파일 오류

 

왜냐하면 컴파일러가 어떤 print() 메서드를 사용해야 하는지 판단하기가 애매하기 때문이다. 물론 다른 타입의 매개변수는 얼마든지 오버로딩이 가능하다.

public void print(String...str) {
	//do something
}

public void print(int num, String...str) {
	//do something
}

 

 

반응형

댓글