Arrays.asListと例外

標準ライブラリ知らなさすぎて何回か同じこと繰り返したので自戒メモ

Arrays.asList(1, 2, 3, 4).add(5);

Arrays.asListの戻り値に対して操作しようとすると例外が投げられるアレ。

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at com.company.Main.main(Main.java:13)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

リストの初期値は<T> List<T> java.util.Arrays.asList(T… a) で設定できる。 - Qiita
のコメントにある通り

new ArrayList(Arrays.asList(1,2,3)).add(5);

な感じで括ってあげる必要がある。

AbstractListの実装を見ると

    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

と内部でこれらを呼んでいるメソッドは例外を投げる。
addAllとか。

ハマった場面はListを返す関数の戻り値がコレを使っていた場合

    public static void main(String[] args) {
        List<String> list = getList();
        list.add("E");
    }

    public static List<String> getList() {
        return Arrays.asList("A", "B", "C", "D");
    }

そもそも外部から取ってきたものの状態を変更しちゃうのもアレですが、標準ライブラリへの理解があれば悩まず回避できた問題でした。