java.lang.UnsupportedOperationException
概要
こちらは、ListやMapなどが固定長な形式な際にaddやputなどをしようとすると発生します。
主に、Collections.emptyList()やCollections.emptyList()、Arrays.asList()などで生成したコレクションオブジェクトにaddやput、removeなどの操作を加えようとすると発生します。
配列をリストに変換する際にArrays.asListはよく使うと思うので、覚えておくと良いでしょう。
finalは関係ない
このエラーが発生した際によく間違えるのが、finalで定義した変数に対して操作をしているから、と勘違いしてしまう人も少なくありません。
finalによる挙動は、一度代入した変数への再代入を防ぐ事になるので、一度代入した変数が持っているメソッドを使って中身を操作する分には問題ありません。
また、エラーのタイミングについても実行時エラーでなくビルドエラーになります。
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
覚えておくと良いでしょう♪
サンプル
MapとListについて簡単なサンプルをまとめてみました。
Map
Collections.emptyMap
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
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
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
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
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でラップすることで可能になるので覚えておくと良いでしょう♪
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");
}
}
終わりに
以上のように、よく使うような記述ですがちょっと使い方を間違えるとバグを潜ませる事になってしまいます。
この辺の挙動の違いを覚えておくだけでも、エンジニアとしてのレベルが少し上がるので是非頭の片隅に置いておくと良いでしょう♪
