성장일기

1. 가변인자(varargs)

 자바에서 기존에는 메소드의 매개변수의 개수가 고정적이었으나 JDK1.5부터 동적으로 지정해 줄 수 있게 되었다.

이 기능을 '가변인자(variable arguments)'라고 한다.

 

가변인자는 '타입... 변수명'과 같은 형식으로 선언하며, PrintStream클래스의 printf()가 대표적인 예이다.

 

 

public PrintStream printf(String format, Object... args){...}

가변인자 외에도 매개변수가 더 있다면, 가변인자를 매개변수 중에서 제일 마지막에 선언해야 한다.

 

 

//컴파일 에러 발생 - 가변인자는 매개변수 마지막에 선언해야 한다.
public PrintStream printf(Object... args, String format){...}

 위와 같은 코드는 가변인자가 앞에 선언됐으므로 컴파일 에러가 발생한다. 가변인자인지 아닌지를 구별할 방법이 없기 때문이다.

 

 

만일 가변인자를 사용하지 않고 여러 문자열을 하나로 결합하여 반환하는 concatenate메소드를 작성한다면, 아래와 같이 매개변수를 다르게 해서 여러 개의 메소드를 작성해야 할 것이다.

String concatenate(String s1, String s2){...}
String concatenate(String s1, String s2, String s3){...}
String concatenate(String s1, String s2, String s3, String s4){...}

 

 

이럴 때 가변인자를 사용하면 메소드 하나로 간단히 해결할 수 있다.

String concatenate(String... str){...}

 

2. 가변인자 호출

메소드를 호출할 때는 아래와 같이 인자의 개수를 가변적으로 지정할 수 있다. 심지어는 인자가 아예 없어도 되고, 타입만 일치한다면 배열도 인자가 될 수 있다.

String concatenetate(String... str){...}

System.out.println(concatenate());	//인자가 없음
System.out.println(concatenate("a"));	//인자가 하나
System.out.println(concatenate("a", "b"));	//인자가 둘
System.out.println(concatenate(new String[]{"a", "b"}));	//배열도 가능

 가변인자는 생략할 수도 있으며 내부적으로 배열을 이용하기 때문에 타입만 같다면 배열도 가능하다. 가변인자는 내부적으로 배열을 이용하기 때문에 가변인자가 선언된 메소드를 호출할 때마다 배열이 새로 생성된다. 가변인자가 편리하지만, 이러한 비효율이 숨어있으므로 꼭 필요한 경우에만 가변인자를 사용하도록 해야한다.

 

 

그렇다면 매개변수로 가변인자로 받는것과 배열로 받는것의 차이를 살펴보면 아래와 같다.

String concatenate(String[] str){...}

System.out.println(concatenate());	//에러. 인자가 필요함
System.out.println(concatenate(null));	//인자로 null을 지정
System.out.println(concatenate(new String[0]));	//인자로 배열을 지정

 매개변수의 타입을 배열로 하면, 반드시 인자를 지정해줘야 하기 때문에, 인자를 생략할 수 없고, null이나 길이가 0인 배열을 인자로 지정해줘야 하는 불편함이 있다.

 

 

3. 가변인자의 오버로딩 - 예제 소스

가변인자를 오버로딩할 때 주의해야할 점이 있다.

public class TestFree {

    public static void main(String[] args) {
        String[] str = {"10", "20", "30"};

        System.out.println(concatenate("", "10", "20", "30"));
        System.out.println(concatenate("-", str));
        System.out.println(concatenate(",", new String[]{"1", "2", "3"}));
        System.out.println("[" + concatenate(",", new String[0]) + "]");

    }

    static String concatenate(String delim, String... args) {
        String result = "";

        for (String str : args) {
            result += str + delim;
        }
        return result;
    }

    /*static String concatenate(String... args) {
        return concatenate("", args);
    }*/

}

실행 결과:

102030
10-20-30-
1,2,3,
[]

 

위의 소스코드에서 concatenate메소드의 또 다른 오버로딩 된 메소드의 주석을 풀면 아래와 같이 컴파일 에러가 발생한다.

에러의 내용을 살펴보면 두 오버로딩 된 메소드를 구분하지 못해서 발생하는 에러임을 알 수 있다. 가변인자를 선언한 메소드를 오버로딩하면, 메소드를 호출했을 때 이와 같이 구별되지 못하는 경우가 발생하기 쉽기 때문에 주의해야 한다.

 

가능하면 가변인자를 사용한 메소드는 오버로딩하지 않는 것이 좋다.

공유하기

facebook twitter kakaoTalk kakaostory naver band