List初期化は「最初の一歩で“性質”を決める」作業
Listの初期化は、単に「空のリストを作る」「要素入りのリストを作る」だけの話に見えますが、
実はこの瞬間に「変更できるか」「スレッドセーフか」「固定サイズか」といった性質が決まります。
業務コードで一番多いバグの一つが、
「あとで要素を追加したいのに、変更できないListを作ってしまった」
「nullを返してしまって、呼び出し側が毎回nullチェックしている」
といった“初期化の設計ミス”です。
だからこそ、「どういう用途のListなのか」を意識して、
それに合った初期化パターンをユーティリティとして持っておくと、
コードの質が一気に安定します。
一番基本:空の可変Listを作る(new ArrayList<>())
「あとで中身を変える前提」の標準形
業務で一番よく使うのは、「最初は空だけど、あとで要素を追加していくList」です。
この場合は、素直に new ArrayList<>() を使うのが基本です。
import java.util.ArrayList;
import java.util.List;
public class ListInitBasic {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("山田");
names.add("佐藤");
System.out.println(names); // [山田, 佐藤]
}
}
Javaここで押さえておきたい重要ポイントは二つです。
一つ目は、「変えられるList(可変List)を作っている」ということです。add や remove が自由にできるので、「あとから増える・減る」前提のデータに向いています。
二つ目は、「変数の型は List、実体は ArrayList」という書き方にしていることです。List<String> names = new ArrayList<>(); のように、
インターフェース型(List)で受けておくと、
あとで実装を LinkedList などに変えたくなったときも、
呼び出し側のコードをほとんど変えずに済みます。
「最初から中身が決まっているList」を作る
Arrays.asList と List.of の違いを理解する
「最初から要素が決まっていて、すぐに使いたい」という場面も多いです。
例えば、固定のコード一覧や、テストデータなどです。
ここでよく使われるのが Arrays.asList と List.of です。
import java.util.Arrays;
import java.util.List;
public class ListInitFixed {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("A", "B", "C");
List<String> list2 = List.of("A", "B", "C");
System.out.println(list1); // [A, B, C]
System.out.println(list2); // [A, B, C]
}
}
Java見た目は同じですが、性質が違います。
ここをきちんと理解しておくことがとても大事です。
Arrays.asList の性質:「サイズ固定」「要素の変更はできる」
add/remove はできないが set はできる
Arrays.asList("A", "B", "C") で作られるListは、
「配列をラップした固定サイズのList」です。
List<String> list = Arrays.asList("A", "B", "C");
list.set(0, "X"); // OK
System.out.println(list); // [X, B, C]
list.add("D"); // ここで例外(UnsupportedOperationException)
list.remove(1); // ここでも例外
Java重要なのは、「サイズは変えられないが、中身の書き換えはできる」という中途半端な性質です。
このせいで、次のような事故が起きやすくなります。
「固定のマスタとして使いたかったのに、どこかで set されて書き換えられてしまった」
「テストで add したら例外が飛んで驚いた」
つまり、Arrays.asList は「配列をListとして一時的に扱いたい」用途には便利ですが、
「業務ロジックで普通に使うList」としては、性質をよく理解していないと危険です。
List.of の性質:「完全に不変(変更不可)」
add/remove/set すべて禁止の“読み取り専用List”
Java 9以降で使える List.of は、
「完全に変更できない不変List」を作ります。
List<String> list = List.of("A", "B", "C");
System.out.println(list); // [A, B, C]
list.set(0, "X"); // 例外(UnsupportedOperationException)
list.add("D"); // 例外
list.remove(1); // 例外
Javaここでの重要ポイントは、「一切変更できない」ということです。
これは逆に言えば、「絶対に書き換えられない保証がある」ということでもあります。
業務で「定数的な一覧」を扱うとき、
例えば「ステータスの候補」「固定のコード一覧」などは、List.of で作っておくと安心です。
public final class Statuses {
private Statuses() {}
public static final List<String> VALID_STATUSES =
List.of("NEW", "IN_PROGRESS", "DONE");
}
Javaこうしておけば、どこかのコードがうっかり add しても例外になり、
「勝手に一覧が変わってしまう」という事故を防げます。
「可変Listが欲しいけど、初期値も入れたい」場合の定番パターン
List.of や Arrays.asList から ArrayList にコピーする
よくあるのが、
「最初からいくつか要素を入れておきたいが、その後も add/remove したい」
というパターンです。
この場合は、「不変Listを元にして、可変Listを作る」という書き方が定番です。
import java.util.ArrayList;
import java.util.List;
public class ListInitMutable {
public static void main(String[] args) {
List<String> base = List.of("A", "B", "C");
List<String> list = new ArrayList<>(base);
list.add("D");
System.out.println(list); // [A, B, C, D]
}
}
Javaあるいは、Arrays.asList からでも同じです。
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
list.add("D");
Javaここでの重要ポイントは、「外から見える型は List、実体は ArrayList」というスタイルを守りつつ、
「初期値入りの可変List」を安全に作っていることです。
null を返さない List初期化ユーティリティという発想
「空のListを返す」ことをルールにするとコードが安定する
業務コードでよくある悪いパターンが、
「要素がなければ null を返す」というメソッドです。
// 悪い例
List<String> findNames() {
if (条件に合うものがなければ) {
return null;
}
...
}
Javaこれをやると、呼び出し側は毎回こう書く必要が出てきます。
List<String> names = findNames();
if (names != null) {
for (String n : names) {
...
}
}
Javanull チェックの書き忘れがバグの温床になります。
そこで、「Listを返すメソッドは、要素がなくても必ず空のListを返す」というルールにしてしまうと、
呼び出し側がとても楽になります。
import java.util.Collections;
import java.util.List;
public final class ListUtils {
private ListUtils() {}
public static <T> List<T> emptyIfNull(List<T> list) {
return (list == null) ? Collections.emptyList() : list;
}
}
Java使い方はこうです。
List<String> names = ListUtils.emptyIfNull(findNames());
for (String n : names) {
...
}
Javaここでの重要ポイントは、「null を“空のList”に正規化する」という発想です。
これにより、「nullかもしれないList」と「空のList」を区別しなくてよくなり、
コードの分岐が減ります。
まとめ:List初期化で本当に意識してほしいこと
List初期化は、単なる new ArrayList<>() や List.of(...) の話ではなく、
「このListは変わるのか、変わらないのか」「nullを返すのか、空を返すのか」
といった設計の話です。
可変Listが欲しいなら new ArrayList<>() を基本形にする。
固定の一覧なら List.of(...) で不変Listにしておく。
初期値入りの可変Listが欲しいなら new ArrayList<>(List.of(...)) のようにコピーする。
メソッドの戻り値としては「nullではなく空のListを返す」ルールにしておく。
もしあなたのコードのどこかに、
if (list == null) { ... }
Javaというnullチェックが何度も出てくるなら、
それを「List初期化とnull正規化のユーティリティ」で置き換えられないか、一度眺めてみてください。
その小さな意識の変化が、
「コレクションの性質を理解して、安定した業務コードを書けるエンジニア」への、
確かな一歩になります。

