개발/Java

가변인자(varargs)

Debin 2022. 2. 27.
반응형

기존에는 메서드의 매개변수 개수가 고정적이었으나,

JDK1.5부터 동적으로 지정해 줄 수 있게 되었으며,

이 기능을 가변 인자라고 한다.

가변 인자는 '타입... 변수명'과 같은 형식으로 선언하며.

 

PrintStream 클래스의 printf()가 대표적인 예다.

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

 

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

그렇지 않다면, 컴파일 에러가 발생한다.

가변 인자인지 아닌지를 구별할 방법이 없기 때문에 허용하지 않는 것이다.

 

이제 아래 코드를 살펴보자.

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) { ... } 

//위 메서드를 사용하면 아래와 같이 인자의 개수를 가변적으로 할 수 있다.

System.out.println(concatenate()); //인자가 없음
System.out.println(concatenate("a")); //인자가 1개
System.out.println(concatenate("a","b")); //인자가 2개
System.out.println(concatenate(new String[]{"A", "B"})); //배열

 

가변인자는 내부적으로 배열을 이용한다.

그래서 가변 인자가 선언된 메서드를 호출할 대마다 배열이 새로 생성된다.

가변 인자 대신 매개변수의 타입을 배열로 사용하면 반드시 인자를 지정해줘야 한다.

그래서 null이나 0인 배열을 인자로 지정해줘야 한다.

 

결국 아래와 같이 배열처럼 사용한다.

class T{
    public void func(String... args){
        System.out.println("args = " + args[0]); //1이 출력된다.
    }
}

public class Main {
    public static void main(String[] args) {
        T m=new T();
        m.func("1","2");
    }
}

 

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

String concatentate(String delim, String... args) { ... }
String concatentate(String... args) { ... }

 

위 두 메서드는 오버 로딩한 메서드로 별 문제가 없어 보인다.

그러나 실행하면 컴파일 오류가 발생한다.

에러의 내용은 두 오버로딩된 메서드가 구분되지 않아서 발생하는 것이다.

가변 인자를 선언한 메서드를 오버 로딩하면,

메서드를 호출했을 때 이와 같이 구별되지 못하는 경우가 발생하기 쉽기 때문에 주의해야 한다.

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

 

참고자료

자바의 정석

반응형

댓글