B-Teck!

お仕事からゲームまで幅広く

【Java】ImmutableなCollectionをJavaで扱う

finalの挙動

Javaのfinalは宣言した変数への代入を禁止するだけで、変数が持っているインスタンスの内容は変更できてしまう。 そのため、Collectionの追加や削除などの操作が行えてしまう。

変更できないCollectionを扱いたい場合、宣言と同時に初期化する インスタンスイニシャライザCollections.unmodifiableXXXメソッド を組み合わせて利用すると良い。

インスタンスイニシャライザ

インスタンスイニシャライザの仕組みを使うと、Collectionを宣言と同時に初期化できる

new ArrayList<String>() {{ add("one"); add("two"); }};
new HashMap<Integer, String>() {{ put(1, "one"); put(2, "two"); }};

操作できないCollectionを作る

java.util.Collectionsには各種Collectionの型に対応した読み取り専用化メソッドがある 各メソッドにCollectionを渡してやると変更不可のCollectionに変換でき、addやputを行うとUnsupportedOperationExceptionがthrowされる。 変換時にnullを渡すとNullPointerExceptionが発生するのでCollections.emptyList()を渡すようにするなど、取り扱いに注意。

また、一度unmodifiableすると変更可能なCollectionにリキャスト等行おうとしてもClassCastExceptionが発生してしまうので注意

unmodifiableCollection(Collection<? extends T> c)
unmodifiableList(List<? extends T> list)
unmodifiableMap(Map<? extends K,? extends V> m)
unmodifiableNavigableMap(NavigableMap<K,? extends V> m)
unmodifiableNavigableSet(NavigableSet<T> s)
unmodifiableSet(Set<? extends T> s)
unmodifiableSortedMap(SortedMap<K,? extends V> m)
unmodifiableSortedSet(SortedSet<T> s)

インスタンスイニシャライザと組み合わせ

static final List<String> list = Collections.unmodifiableList( new ArrayList<String>() {{ add("one"); add("two"); }} );
static final Map<Integer, String> map = Collections.unmodifiableMap(new HashMap<Integer, String>() {{ put(1, "one"); put(2, "two"); }} );