List.of()가 무한으로 인자값을 받을 수 있는 이유

SionBackEnd·2023년 5월 1일
0

자바 스터디

목록 보기
21/21

소개

주로 테스트 코드를 작성할 때 List.of()를 이용하여 List를 생성하곤 했다.
사용할 때는 당연히 List.of() = 파라미터 값의 제한이 없다. 라고 생각하며 사용했다.
하지만, 이전 블로깅에서 Map.of()에 대해서 알아가다 보니 이 부분도 궁금해졌다.

구현 로직

구현 로직을 살펴보고 약간 놀랐다.

static <E> List<E> of() {
        return ImmutableCollections.emptyList();
    }

    /**
     * Returns an unmodifiable list containing one element.
     *
     * See <a href="#unmodifiable">Unmodifiable Lists</a> for details.
     *
     * @param <E> the {@code List}'s element type
     * @param e1 the single element
     * @return a {@code List} containing the specified element
     * @throws NullPointerException if the element is {@code null}
     *
     * @since 9
     */
    static <E> List<E> of(E e1) {
        return new ImmutableCollections.List12<>(e1);
    }

    /**
     * Returns an unmodifiable list containing two elements.
     *
     * See <a href="#unmodifiable">Unmodifiable Lists</a> for details.
     *
     * @param <E> the {@code List}'s element type
     * @param e1 the first element
     * @param e2 the second element
     * @return a {@code List} containing the specified elements
     * @throws NullPointerException if an element is {@code null}
     *
     * @since 9
     */
    static <E> List<E> of(E e1, E e2) {
        return new ImmutableCollections.List12<>(e1, e2);
    }
    
    ...
    
    {생략}
    
    ...
    
    
    /**
     * Returns an unmodifiable list containing ten elements.
     *
     * See <a href="#unmodifiable">Unmodifiable Lists</a> for details.
     *
     * @param <E> the {@code List}'s element type
     * @param e1 the first element
     * @param e2 the second element
     * @param e3 the third element
     * @param e4 the fourth element
     * @param e5 the fifth element
     * @param e6 the sixth element
     * @param e7 the seventh element
     * @param e8 the eighth element
     * @param e9 the ninth element
     * @param e10 the tenth element
     * @return a {@code List} containing the specified elements
     * @throws NullPointerException if an element is {@code null}
     *
     * @since 9
     */
    static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
        return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
                                                e6, e7, e8, e9, e10);
    }

    /**
     * Returns an unmodifiable list containing an arbitrary number of elements.
     * See <a href="#unmodifiable">Unmodifiable Lists</a> for details.
     *
     * @apiNote
     * This method also accepts a single array as an argument. The element type of
     * the resulting list will be the component type of the array, and the size of
     * the list will be equal to the length of the array. To create a list with
     * a single element that is an array, do the following:
     *
     * <pre>{@code
     *     String[] array = ... ;
     *     List<String[]> list = List.<String[]>of(array);
     * }</pre>
     *
     * This will cause the {@link List#of(Object) List.of(E)} method
     * to be invoked instead.
     *
     * @param <E> the {@code List}'s element type
     * @param elements the elements to be contained in the list
     * @return a {@code List} containing the specified elements
     * @throws NullPointerException if an element is {@code null} or if the array is {@code null}
     *
     * @since 9
     */
    @SafeVarargs
    @SuppressWarnings("varargs")
    static <E> List<E> of(E... elements) {
        switch (elements.length) { // implicit null check of elements
            case 0:
                return ImmutableCollections.emptyList();
            case 1:
                return new ImmutableCollections.List12<>(elements[0]);
            case 2:
                return new ImmutableCollections.List12<>(elements[0], elements[1]);
            default:
                return new ImmutableCollections.ListN<>(elements);
        }
    }

10개의 파라미터를 허용하는 List.of()가 오버로딩 되어 있고, 가변인자를 받는 List.of()가 오버로딩 되어 있었다..

아니 가변인자로만 설정이 되어 있는줄 예상했지만, 의문이였다. 그래서 가변인자에 대해서 좀더 알아보게 되었다.
답은 이펙티브 자바 Item.53 가변인수는 신중히 사용해라 챕터에서 알 수 있었다.

성능에 민감한 상황이라면 가변인수가 걸림돌이 될 수 있다. 가변인수 메서드는 호출될 때마다 배열을 새로 하나 할당하고 초기화한다. 다행히, 이 비용을 감당할 수는 없지만 가변인수의 유연성이 필요할 때 선택할 수 있는 멋진 패턴이 있다. 예를 들어 해당 메서드 호출의 95%가 인수를 3개 이하로 사용한다고 해보자. 그렇다면 다음처럼 인수가 0개인 것부터 4개인 것까지, 총 5개를 다중정의하자. 마지막 다중정의 메서드가 인수 4개 이상인 5%의 호출을 담당하는 것이다.

-알라딘 eBook <이펙티브 자바> (조슈아 블로크 지음, 개앞맵시 옮김) 중에서

가변인자가 생각보다 효율이 떨어지기 때문에 10개의 파라미터까지는 오버로딩 해두고 그 이상은 성능을 포기하더라도 자율성을 준것이라고 생각이 들었다.

이 부분을 학습하면서 느낀점은 효율성을 위해서 약간의 번거로움은 감수해야 한다고 느끼게 되었다.
또한 자바에서 제공해주는 메서드가 어떻게 구현이 되어 있는지를 확인해서 성능부분에 신경을 쓰도록 해야겠다.

profile
많은 도움 얻어가시길 바랍니다!

0개의 댓글