Featured image of post 【コレクションオブジェクト】要素を操作した際にUnsupportedOperationExceptionが出る原因と対応方法【Java】

【コレクションオブジェクト】要素を操作した際にUnsupportedOperationExceptionが出る原因と対応方法【Java】

927文字

java.lang.UnsupportedOperationException

概要

こちらは、ListMapなどが固定長な形式な際にaddputなどをしようとすると発生します。

主に、Collections.emptyList()Collections.emptyList()Arrays.asList()などで生成したコレクションオブジェクトにaddputremoveなどの操作を加えようとすると発生します。

配列をリストに変換する際にArrays.asListはよく使うと思うので、覚えておくと良いでしょう。

finalは関係ない

このエラーが発生した際によく間違えるのが、finalで定義した変数に対して操作をしているから、と勘違いしてしまう人も少なくありません。

finalによる挙動は、一度代入した変数への再代入を防ぐ事になるので、一度代入した変数が持っているメソッドを使って中身を操作する分には問題ありません

また、エラーのタイミングについても実行時エラーでなくビルドエラーになります。

App.java
package app;

import java.util.ArrayList;
import java.util.List;

public class App {
    public static void main(String[] args) {
        final List<String> arraysList = new ArrayList<>();
        arraysList = new ArrayList<>();
        arraysList.add("value");
    }
}

ビルドエラー
App.java:13: error: cannot assign a value to final variable arraysList
        arraysList = new ArrayList<>();
        ^
1 error

覚えておくと良いでしょう♪

サンプル

MapListについて簡単なサンプルをまとめてみました。

Map

Collections.emptyMap

[adsense-responsive]

App.java
package app;

import java.util.Collections;
import java.util.Map;

public class App {
    public static void main(String[] args) {
        Map<String, String> emptyMap = Collections.emptyMap();
        emptyMap.put("a", "value");
    }
}

実行時エラー
Exception in thread "main" java.lang.UnsupportedOperationException
        at java.base/java.util.AbstractMap.put(AbstractMap.java:209)
        at app.App.main(App.java:9)

new HashMap

App.java
package app;

import java.util.HashMap;
import java.util.Map;

public class App {
    public static void main(String[] args) {
        Map<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("a", "value");
    }
}

こちらは正常に処理が終了します。

List

Collections.emptyList

App.java
package app;

import java.util.Collections;
import java.util.List;

public class App {
    public static void main(String[] args) {
        List<String> emptyList = Collections.emptyList();
        emptyList.add("value");
    }
}

実行時エラー
Exception in thread "main" java.lang.UnsupportedOperationException
        at java.base/java.util.AbstractList.add(AbstractList.java:153)
        at java.base/java.util.AbstractList.add(AbstractList.java:111)
        at app.App.main(App.java:9)

new ArrayList

App.java
package app;

import java.util.ArrayList;
import java.util.List;

public class App {
    public static void main(String[] args) {
        List<String> arrayList = new ArrayList<String>();
        arrayList.add("value");
    }
}

こちらは正常に処理が終了します。

Arrays.asList

App.java
package app;

import java.util.Arrays;
import java.util.List;

public class App {
    public static void main(String[] args) {
        List<String> asList = Arrays.asList();
        asList.add("value");
    }
}

実行時エラー
Exception in thread "main" java.lang.UnsupportedOperationException
        at java.base/java.util.AbstractList.add(AbstractList.java:153)
        at java.base/java.util.AbstractList.add(AbstractList.java:111)
        at app.App.main(App.java:9)

Arrays.asListで変換したリストに操作を加えたい場合

Arrays.asListを使って生成したリストに操作を加えたい場合は、以下のようにnew ArrayListでラップすることで可能になるので覚えておくと良いでしょう♪

[adsense-responsive]

App.java
package app;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class App {
    public static void main(String[] args) {
        List<String> asList = Arrays.asList();
        List<String> arrayList = new ArrayList<String>(asList);
        arrayList.add("value");
    }
}

終わりに

以上のように、よく使うような記述ですがちょっと使い方を間違えるとバグを潜ませる事になってしまいます。

この辺の挙動の違いを覚えておくだけでも、エンジニアとしてのレベルが少し上がるので是非頭の片隅に置いておくと良いでしょう♪