ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 가변인자(varargs)는 실제 런타임(Runtime) 시 어떻게 작동 할까?
    Develop/Java 2022. 9. 13. 11:19

    가변인자 란?

    • 기존에는 메서드의 매개변수의 개수가 고정적이어서 컬렉션이나 배열을 통해 사용했다.
    • JDK1.5부터 동적으로 매개변수를 지정하는 가변인자라는 것이 생겼다.
    • 아래와 같이 파라미터 변수에 ...을 파라미터 변수명 앞에 붙여주면 된다.
    public void testVarargs(String... d) {
        //...
    }

     

     

    • 가변인자를 사용하는 대표적인 메소드는 PrintStream의 printf()이다.
    /*
     * @since  1.5
     */
    public PrintStream printf(String format, Object ... args) {
        return format(format, args);
    }

     

    사용 시 주의 할 점

    • 가변인자는 여러개 사용될 수 없고, 가변인자는 항상 마지막에 있어야 한다. (가변인자인지 아닌지를 구분할 방법이 없기 때문)

     

    • 가변인자 사용 시 인자를 넣지 않아도 정상적으로 실행이 된다.

     

    • 가변인자 앞에 동일한 타입의 매개변수를 오버로딩 시 구별 못한다는 이유(ambiguous)로 허용하지 않는다.

     

     

     

    매개변수를 가변인자와 배열로 선언하는 것과 차이?

    • 배열타입의 경우 반드시 인자를 지정해줘야하기 때문에 인자를 생략할 수가 없다. (null이나 0인 배열을 인자로 지정해줘야 함)

     

     

    바이트코드에서 확인

    소스 코드

    import java.util.Arrays;
    
    public class TestV {
    
        public static void main(String[] args) {
            varargsTest(5, "1", "2", "3");
        }
    
        public static void varargsTest(int a, String... str) {
            System.out.println(Arrays.toString(str));
        }
    
    }

     

    • Arrays.toString을 활용해야 하는 것을 보아 가변인자를 거쳐서 넘어오는 args의 인자들은 배열의 형태로 변환된다는 사실을 확인할 수 있다.

     

    바이트 코드

    public static main([Ljava/lang/String;)V
        // parameter  args
       L0
        LINENUMBER 9 L0
        ICONST_5
        ICONST_3
        ANEWARRAY java/lang/String // 객체 타입 배열 생성
        DUP
        ICONST_0
        LDC "1"
        AASTORE // 배열에 "1" 저장
        DUP
        ICONST_1
        LDC "2"
        AASTORE // 배열에 "2" 저장
        DUP
        ICONST_2
        LDC "3"
        AASTORE // 배열에 "3" 저장
        INVOKESTATIC com/example/test/TestV.varargsTest (I[Ljava/lang/String;)V 
        // varargsTest 메소드 호출, [Ljava/lang/String;) 가변인자 호출
       L1
        LINENUMBER 10 L1
        RETURN
       L2
        LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
        MAXSTACK = 5
        MAXLOCALS = 1
    
      // access flags 0x89
      public static varargs varargsTest(I[Ljava/lang/String;)V
        // parameter  a
        // parameter  str
       L0
        LINENUMBER 13 L0
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        ALOAD 1
        INVOKESTATIC java/util/Arrays.toString ([Ljava/lang/Object;)Ljava/lang/String;
        INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
       L1
        LINENUMBER 14 L1
        RETURN
       L2
        LOCALVARIABLE a I L0 L2 0
        LOCALVARIABLE str [Ljava/lang/String; L0 L2 1 
        // str 매개변수가 [Ljava/lang/String;(일반 배열형태로) 변환됨을 확인할 수 있다.
        MAXSTACK = 2
        MAXLOCALS = 2
    }

     

    결론

    • ...이라는 표시를 해두면 컴파일러는 배열 형태로 바꾼다.
    • 매개변수 파라미터를 배열로 하는경우는 인자를 반드시 넣어야 하지만(null 이나 0인 배열), 가변인자는 그렇지 않다. 

    댓글

Designed by Tistory.