본문 바로가기
Programming Language/Java

[Java] List.of를 사용한 초기화

by kimyoungrok 2025. 2. 13.
728x90

목차

  • UnsupportedOperationException
  • List.of()를 사용한 초기화
  • 컬렉션 생성자의 동작 원리
  • 정리

Java 9부터 도입된 List.of()는 불변 리스트(Immutable List)를 생성하는 편리한 메서드입니다. 하지만 이 불변 리스트에 직접 요소를 추가하려고 하면 UnsupportedOperationException이 발생합니다. 그런 반면 List.of()로 생성된 불변 리스트를 컬렉션의 초기값으로 전달 후 컬렉션에 요소를 추가하면 예외가 발생하지 않습니다.

이번 글에서는 List.of()로 생성된 불변 리스트와, 이를 컬렉션의 생성자로 전달할 때 내부적으로 어떻게 동작하는지 살펴보겠습니다.


UnsupportedOperationException

Java에서 List.of()는 불변 리스트(Immutable List)를 생성합니다. 일반적으로 불변 리스트에 요소를 추가하면 아래와 같이 UnsupportedOperationException이 발생합니다

SampleUnsupportedOperationException.java

package pl.java.listof;

import java.util.List;

public class SampleUnsupportedOperationException {
    public static void main(String[] args) {
        List<Integer> list = List.of(0);
        list.add(1); // 예외 발생!
    }
}
/*
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
	at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
	at pl.java.listof.SampleUnsupportedOperationException.main(SampleUnsupportedOperationException.java:8)
*/

List.of()를 사용한 초기화

하지만 다음과 같이 List.of()로 생성한 불변 리스트를 다른 컬렉션의 초기값으로 사용하는 경우, 정상적으로 작동하는 것을 확인할 수 있습니다.

ImmutableListInitializer.java

package pl.java.listof;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;

public class ImmutableListInitializer {
    public static void main(String[] args) {
        Deque<Integer> pq = new ArrayDeque<>(List.of(1, 2, 3));
        pq.add(4);

        System.out.println(pq);
    }
}
/*
[1, 2, 3, 4]
*/

왜 같은 불변 리스트를 사용했음에도 불구하고, ArrayDeque는 요소 추가가 가능한 것일까요?


컬렉션 생성자의 동작 원리

ArrayDeque의 생성자를 보면, 전달 받은 컬렉션을 그대로 참조하는 것이 아니라 내부적으로 복사하는 것을 알 수 있습니다.

    public ArrayDeque(Collection<? extends E> c) {
        this(c.size());
        copyElements(c);
    }
    private void copyElements(Collection<? extends E> c) {
        c.forEach(this::addLast);
    }
    public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        final Object[] es = elements;
        es[tail] = e;
        if (head == (tail = inc(tail, es.length)))
            grow(1);
    }

정리

  • List.of()는 불변 리스트를 생성하므로 add(), remove() 드의 변경 작업 시 UnsupportedOperationException가 발생한다.
  • 대부분의 표준 컬렉션들은 Collection을 인자로 받는 생성자를 제공하므로 List.of()로 생성된 불변리스트로도 생성이 가능하다.
  • 불변 리스트로 초기화된 컬렉션은 원본 리스트를 참조하는 것이 아닌, 복사하므로 이후 해당 컬렉션은 정상적으로 요소 추가/삭제 등의 작업을 수행할 수 있다.
728x90