AIによる要約
Arrays.asListが返すListは配列をListとして見せる固定長のビューです。setによる要素の置換はできますが、addやremoveで要素数を変えるとUnsupportedOperationExceptionになります。List.ofは追加・削除・置換ができず、nullも許可しません。追加や削除が必要ならnew ArrayList<>(...)で可変リストを作ります。「List型だから変更できる」と判断せず、生成方法と所有者を確認することが重要です。


Javaの業務システムでは、固定値、検索結果、CSV列、画面の選択肢などをListで扱います。見た目は同じ`List<String>`でも、`ArrayList`、`Arrays.asList`、`List.of`では変更できる範囲が異なります。
この違いを知らないと、開発環境では通った処理が特定データで突然`UnsupportedOperationException`になったり、共通定数を意図せず書き換えたりします。API名の暗記ではなく、要素数を変えるか、要素を置き換えるか、nullを許すかで判断しましょう。
この記事のポイント
- Arrays.asListは固定長でadd・removeできない
- Arrays.asListはsetでき、元配列と値が連動する
- List.ofはadd・remove・setできずnullも許可しない
- 変更が必要ならnew ArrayList<>でコピーする
- 引数として受け取ったListを勝手に変更しない
Xのクイズ:Arrays.asListへaddできるか

List<String> names =
Arrays.asList("A", "B");
names.add("C");
System.out.println(names);`names.add("C")`で`UnsupportedOperationException`が発生します。`Arrays.asList`は`java.util.Arrays.ArrayList`という内部クラスを返しますが、通常使う`java.util.ArrayList`とは別物です。
Arrays.asListは配列をListとして扱う固定長ビュー
`Arrays.asList`が返すListは、渡した配列を背後に持ちます。配列の長さは作成後に変えられないため、List側でも要素数を増減できません。
String[] array = {"A", "B"};
List<String> list = Arrays.asList(array);
list.set(0, "X");
System.out.println(Arrays.toString(array)); // [X, B]
array[1] = "Y";
System.out.println(list); // [X, Y]`set`による置換はできます。そしてListを変更すると元配列も変わり、元配列を変更するとListにも反映されます。コピーではなく、同じ要素を別の見せ方で扱っている点が重要です。
| 操作 | Arrays.asList |
|---|---|
| get | できる |
| set | できる |
| add | できない |
| remove | できない |
| null要素 | 扱える |
| 元配列との連動 | する |
変更したいならArrayListへコピーする
List<String> names =
new ArrayList<>(Arrays.asList("A", "B"));
names.add("C");
names.remove("A");
System.out.println(names); // [B, C]`new ArrayList<>(...)`は要素を新しい可変リストへコピーします。元配列と切り離されるため、追加・削除・置換が可能です。
Java 9以降なら、初期値を`List.of`で表し、それをArrayListへコピーする書き方もできます。
List<String> names =
new ArrayList<>(List.of("A", "B"));
names.add("C");Xのクイズ:List.ofはnullを持てるか

List<String> values = List.of(
"A", null, "C");このコードは`NullPointerException`になります。List.ofは変更不可であるだけでなく、null要素も許可しません。元のクイズはXの出題ポストと回答ポストにあります。
List.ofは変更不可の値を表す
List<String> roles = List.of("USER", "ADMIN");
roles.add("AUDITOR"); // UnsupportedOperationException
roles.set(0, "GUEST"); // UnsupportedOperationExceptionList.ofで作ったListは、add・remove・setのすべてができません。「この一覧は作成後に変わらない」という意図をコードで表せます。権限種別や固定ステータスなど、共通定数を誤って変更されたくない場面に向いています。
ただし変数を`final`にするだけではListの中身は守れません。`final List<String> list = new ArrayList<>();`は、別のListを再代入できないだけで、`list.add`は可能です。中身の変更を防ぐにはList.ofや`List.copyOf`などを使います。
ArrayList・Arrays.asList・List.ofの違い
| 作り方 | add/remove | set | null | 主な用途 |
|---|---|---|---|---|
| new ArrayList<>() | 可能 | 可能 | 可能 | 後から編集する一覧 |
| Arrays.asList(array) | 不可 | 可能 | 可能 | 既存配列をList APIで扱う |
| List.of(...) | 不可 | 不可 | 不可 | 変更しない固定値 |
| List.copyOf(list) | 不可 | 不可 | 不可 | 受け取った一覧の変更不可コピー |
「どれが新しいAPIか」ではなく、作成後に誰がどの操作をするのかで選びます。
現場で起きる典型的な不具合
固定値へ条件付き要素を追加する
List<String> columns = List.of("id", "name");
if (includeEmail) {
columns.add("email");
}テストで`includeEmail=false`しか通らなければ問題は見えません。本番でtrueになった時だけ例外になります。追加する可能性がある時点でArrayListを選びます。
List<String> columns =
new ArrayList<>(List.of("id", "name"));
if (includeEmail) {
columns.add("email");
}引数として受け取ったListを直接変更する
void normalize(List<String> values) {
values.removeIf(String::isBlank);
}呼び出し元がList.ofを渡すと例外になります。また可変Listでも、呼び出し元が保持する一覧まで変わります。メソッド内だけで加工するならコピーを作ります。
List<String> normalize(List<String> values) {
List<String> result = new ArrayList<>(values);
result.removeIf(String::isBlank);
return result;
}Arrays.asListのsetで元配列まで変える
外部ライブラリへ渡す配列をArrays.asListでラップし、画面表示用にsetした結果、後続の送信データまで変わることがあります。元配列を変更してよいか判断できない場合は、`new ArrayList<>(Arrays.asList(array))`で分離します。
テストでは例外になる操作も確認する
@Test
void Arrays_asListには追加できない() {
List<String> values = Arrays.asList("A", "B");
assertThrows(
UnsupportedOperationException.class,
() -> values.add("C"));
}
@Test
void List_ofはnullを許可しない() {
assertThrows(
NullPointerException.class,
() -> List.of("A", null));
}
@Test
void ArrayListへコピーすれば追加できる() {
List<String> values =
new ArrayList<>(List.of("A", "B"));
values.add("C");
assertEquals(List.of("A", "B", "C"), values);
}現場レビューでよくある指摘
// レビューコメント例
Arrays.asListの戻り値は固定長なのでaddできません。
追加が必要ならArrayListへコピーしてください。
// レビューコメント例
この一覧は固定値として扱うため、可変なArrayListではなく
List.ofで変更不可にすると意図が伝わります。
// レビューコメント例
引数のListを直接変更すると呼び出し元へ副作用が出ます。
メソッド内でコピーしてから加工してください。提出前のセルフチェック
- ListをどのAPIで作ったか確認したか
- add・remove・setのどれが必要か整理したか
- Arrays.asListと元配列が連動してもよいか
- List.ofへnullが入る可能性はないか
- 変更が必要ならArrayListへコピーしたか
- 変更不要ならList.ofやList.copyOfを検討したか
- 引数として受け取ったListを直接変更していないか
- 条件分岐のtrue側もテストしたか
Javaコレクションを基礎から学ぶ参考書
List、Set、Mapの生成方法と変更操作を体系的に整理しておくと、実装クラスによる違いをレビュー前に判断しやすくなります。
スッキリわかるJava入門 第5版
Java文法とオブジェクト指向を、最初から整理する一冊。
豊富な図とサンプルで、変数、条件分岐、クラス、例外処理まで順番に学べます。Javaの最初の教科書を探している人向けです。
- Javaを基礎から体系的に学びたい
- Java 25 LTS対応の入門書を選びたい
当サイトはAmazonアソシエイト・プログラムの参加者です。価格・在庫・配送条件はAmazonでご確認ください。
この記事とあわせて読みたい
まとめ
Arrays.asListは配列をListとして扱う固定長ビューなので、setはできますがadd・removeはできません。元配列と値が連動することにも注意が必要です。
List.ofは追加・削除・置換ができず、nullも許可しません。変更が必要ならArrayList、変更しないならList.of、配列との橋渡しならArrays.asListというように、作成後の操作と所有者から選びましょう。
