Java9 불변 컬렉션

지니·2022년 11월 7일
0

1. Java9의 불변 컬렉션 생성

1. List

1) List.of()

List<String> animalList = List.of("Dog", "Cat", "Duck");
  • 비어있는 리스트를 만들기 위해서는 List.of() 를 사용하면 된다.
  • animalList.add("???") 처럼 뭔가를 넣으면 UnsupportedOperationException이 터진다.

2. Set

1) Set.of()

Set<String> animalSet = Set.of("Dog", "Cat", "Duck");
  • of()에 중복 인자가 들어갈 경우 IllegalArgumentException이 발생한다.

3. Map

1) Map.of()

Map<Integer, String> animalMap = Map.of(1, "Dog", 2, "Cat", 3, "Duck");

2) Map.ofEntries()

Map<Integer, String> animalMap = Map.ofEntries(entry(1,"Dog"), entry(2,"Cat"), entry(3,"Duck"));
  • 둘 다 animalMap.add(4, "???") 처럼 뭔가를 넣으면 UnsupportedOperationException이 터진다.





2. 불변 컬렉션 구성

왜 UnsupportedOperationException이 터지는지 알아보자.


1. List.of(), Set.of(), Map.of()

1) 불변 List, Set, Map

ImmutableCollections.java

class ImmutableCollections {
	
    ...
    
    @jdk.internal.ValueBased
    static abstract class AbstractImmutableCollection<E> extends AbstractCollection<E> {
        // all mutating methods throw UnsupportedOperationException
        @Override public boolean add(E e) { throw uoe(); }
        @Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
        @Override public void    clear() { throw uoe(); }
        @Override public boolean remove(Object o) { throw uoe(); }
        @Override public boolean removeAll(Collection<?> c) { throw uoe(); }
        @Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
        @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
    }
    
    ...
    
    @jdk.internal.ValueBased
    static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>
            implements List<E>, RandomAccess {
            
    }
    
    ...
    
    @jdk.internal.ValueBased
    static abstract class AbstractImmutableSet<E> extends AbstractImmutableCollection<E>
            implements Set<E> {
            
    }
    
    @jdk.internal.ValueBased
    abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable {
    
    }
}
  • ImmutableCollections 클래스 내 AbstractImmutableList와 AbstractImmutableSet은 위의 AbstractImmutableCollection을 상속받고 있다.
  • 상위 클래스인 AbstractImmutableCollection은 불변 컬렉션에 대해 변형시키는 메소드를 호출할 시 UnsupportedOperationException을 던지고 있다.
  • AbstractImmutableMap은 AbstractMap을 상속받고 있는데 기본적으로 AbstractMap에서 put() 과 같은 연산을 하면 UnsupportedOperationException을 던진다.


2) static of()로 객체 생성 후 add(), put() 했을 때 UnsupportedOperationException 발생하는 이유

  • List, Set, Map은 공통적으로 of()를 통해 객체를 생성할 수 있다.
  • 해당 불변 컬렉션 어떻게 구성되어 있는지 대표적으로 Set을 통해 알아볼 예정이다.
    (나머지도 거의 유사하게 구성되어 있다.)

ImmutableCollections.java

class ImmutableCollections {
	@jdk.internal.ValueBased
    static final class Set12<E> extends AbstractImmutableSet<E>
            implements Serializable {
}

Set.java

public interface Set<E> extends Collection<E> {
    @SuppressWarnings("unchecked")
    static <E> Set<E> of() {
        return (Set<E>) ImmutableCollections.EMPTY_SET;
    }
    
    static <E> Set<E> of(E e1) {
        return new ImmutableCollections.Set12<>(e1);
    }
}
  • of() 메소드에서 Set12 객체를 생성하고 있다.
  • Set12는 위의 AbstractImmutableSet을 상속받고 있고 이는 불변객체가 생성됨을 의미한다.




참고
Java9의 불변 컬렉션 생성

profile
Coding Duck

0개의 댓글