[Effective Java 3/E] ITEM 53. 가변인수는 신중히 사용하라

    Effective Java 표지. Source : https://blog.insightbook.co.kr/

    *알림 : *
    Effective Java 3판은 Java 9까지 도입된 언어적 기능을 중심으로 서술되어 있습니다. 10버젼 이후의 Java 개발을 하시는 분들은 우회적인 접근법 대신 Java 언어 내 새로 도입된 기능이 더 간결하고 좋을 수 있습니다.

    해당 포스팅은 SSAFY 내 책읽기 스터디의 활동을 통해 작성된 포스팅입니다.
    https://github.com/kjsu0209/JavaBook
    https://medium.com/javabook

     

    JavaBook – Medium

    Documentation space of our book study.

    medium.com

     

    kjsu0209/JavaBook

    책읽기 스터디. Contribute to kjsu0209/JavaBook development by creating an account on GitHub.

    github.com

    가변인수는 명시한 타입의 0개 이상, 갯수가 정해지지 않았지만 원하는 만큼 매개변수를 받을 수 있는 Java의 언어적 기능이다.

    예제 1 : 가변인수를 사용한 합 구하기

            static int sum(int... args) {
            int sum = 0;
            for (int arg : args)
                sum += arg;
            return sum;
        }

    가변인수를 최소 1개 이상 받도록 강제하는 테크닉

    예제 2 : 최솟값을 구하는 가변인수를 사용한 메서드

        static int min(int... args) {
            if (args.length == 0)
                throw new IllegalArgumentException("인수가 1개 이상 필요합니다.");
            int min = args[0];
            for (int i = 1; i < args.length; i++)
                if (args[i] < min)
                    min = args[i];
            return min;
        }

    인수가 0개이면, 최솟값은 정의가 되지 않을 것이다. 코드도 지저분해질 수 밖에 없고, 가장 중요한건 컴파일 타임에 이 문제를 잡지 못하고 런타임에 문제를 확인한다.

    대신 매개변수 하나를 받고 가변인수를 하나, 총 2개를 받으면 최소 1개의 매개변수를 넣도록 강제할 수 있다.

    예제 3 : 평범한 인자 + 가변인수로 최소 1개 이상의 인자 강제하기

            static int min(int firstArg, int... remainingArgs) {
            int min = firstArg;
            for (int arg : remainingArgs)
                if (arg < min)
                    min = arg;
            return min;
        }

    가변인수 성능 최적화하기

    가변인수는 내부적으로 배열을 생성한다. 메서드가 호출될 때 마다 배열을 만들어 전달하는 과정에서 오버헤드가 발생한다. 가변인수가 필요한 상황에서 오버헤드를 최소한으로 줄이고 싶다면, 프로파일링을 통해 인수가 몇 개인 메서드가 가장 자주 쓰이는지 수치를 얻어낸 다음, 호출의 대부분을 차지하는 범위까지 일반인자를 통해 메서드를 정의한다. 만약 인자 3개짜리 메서드가 대부분의 호출을 담당한다면, 아래와 같이 만들 수 있다.

    예제 4 : 다중정의로 가변인수 최적화하기

    public void foo(){}
    public void foo(int a1){}
    public void foo(int a1, int a2){}
    public void foo(int a1, int a2, int a3){}
    public void foo(int a1, int a2, int a3, int... rest){}

    Java API에서 EnumSet.of가 이 구현을 충실히 따르고 있다.

    참조하기 : EnumSet.java Line 200~

    댓글