방어적 복사에 대해 공부하다가 읽기 전용 List 를 반환하는 unmodifiableList 에 대해서 알게 되었다.

그리고 List.copyOf 또한 읽기 전용 List 를 반환한다는 것을 알게 되었다. 조금 더 자세히 파악해보자.

public List<Card> getValue() {
        return List.copyOf(value);
}

내부 구현 로직

내부 구현 로직을 살펴보니 unmodifiableList 와 똑같이 get 을 제외한 다른 메서드를 호출 할 경우

에러를 던지도록 구현했다. 차이점은 List 원본을 복사한 값을 읽기 전용으로 만든다.

private ImmutableCollections() { }

/**
 * The reciprocal of load factor. Given a number of elements
 * to store, multiply by this factor to get the table size.
 */
static final intEXPAND_FACTOR= 2;

static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }

static abstract class AbstractImmutableCollection<E> extends AbstractCollection<E> {
    // all mutating methods throw UnsupportedOperationException
    @Override public boolean add(E e) { throwuoe(); }
    @Override public boolean addAll(Collection<? extends E> c) { throwuoe(); }
    @Override public void    clear() { throwuoe(); }
    @Override public boolean remove(Object o) { throwuoe(); }
    @Override public boolean removeAll(Collection<?> c) { throwuoe(); }
    @Override public boolean removeIf(Predicate<? super E> filter) { throwuoe(); }
    @Override public boolean retainAll(Collection<?> c) { throwuoe(); }
}

// ---------- List Implementations ----------

// make a copy, short-circuiting based on implementation class
@SuppressWarnings("unchecked")
static <E> List<E> listCopy(Collection<? extends E> coll) {
    if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
        return (List<E>)coll;
    } else {
        return (List<E>)List.of(coll.toArray());
    }
}

참고