空List安全取得は「null を“空”にそろえる」ための小さな約束
List を返すメソッドって、業務コードに山ほど出てきますよね。
検索結果、関連データ、設定値の一覧、などなど。
そこでよく起きるのが、このパターンです。
List<String> result = findNames();
if (result != null) {
for (String name : result) {
...
}
}
Java毎回 result != null を書いていると、どこかで必ず書き忘れます。
そして、NullPointerException が飛ぶ。
空List安全取得は、ここを「そもそも null を返さない世界」に変えるためのユーティリティです。
「null かもしれない List」を、「必ず空か要素ありの List」に正規化するイメージです。
基本アイデア:null なら空Listに変換する
emptyIfNull という“正規化関数”を用意する
まずは、どんな List が来ても「null なら空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 = null;
List<String> safe = ListUtils.emptyIfNull(names);
System.out.println(safe.size()); // 0
for (String n : safe) { // nullチェック不要
System.out.println(n);
}
Javaここで重要なのは、次の2点です。
一つ目は、「呼び出し側が null を意識しなくてよくなる」ことです。emptyIfNull を通した時点で、「この List は null ではない」と保証されるので、
for-each も list.size() も安心して呼べます。
二つ目は、「null と“要素がない”を同じ扱いにする」という設計を、
ユーティリティに閉じ込めていることです。
「該当なし=空List」というルールを徹底すると、
コード全体の分岐がかなり減ります。
呼び出し側のコードがどう変わるかを比べてみる
before:毎回 null チェックが必要な世界
従来の書き方だと、こうなりがちです。
List<String> names = findNames();
if (names != null && !names.isEmpty()) {
for (String n : names) {
...
}
}
Javanames != null を書き忘れると NPE。isEmpty() を書き忘れると、無駄なループ。
after:空List安全取得を使った世界
空List安全取得を挟むと、こう書けます。
List<String> names = ListUtils.emptyIfNull(findNames());
for (String n : names) {
...
}
Java「null かもしれない」という不安を、emptyIfNull の中に押し込めてしまったイメージです。
ここで深掘りしたいポイントは、「null チェックの責任の場所を変えている」ということです。
今までは「呼び出し側が毎回責任を負っていた」のを、
「ユーティリティが一度だけ責任を負う」形に変えています。
戻り値側で「最初から空Listを返す」設計にする
そもそも null を返さないメソッドにする
もっと理想を言えば、
「List を返すメソッドは、null ではなく空Listを返す」
というルールにしてしまうのがベストです。
import java.util.Collections;
import java.util.List;
public class NameRepository {
public List<String> findNames() {
List<String> result = ...; // DBなどから取得
if (result == null || result.isEmpty()) {
return Collections.emptyList();
}
return result;
}
}
Javaこうしておけば、呼び出し側は emptyIfNull すら要りません。
List<String> names = nameRepository.findNames();
for (String n : names) {
...
}
Javaここでの重要ポイントは、「null を返すかどうかは“設計の約束事”」だということです。
「このプロジェクトでは、コレクションの戻り値に null は使わない」
と決めてしまえば、空List安全取得は「外部ライブラリや古いコードと接続するとき」だけに使えばよくなります。
Collections.emptyList() と new ArrayList<>() の違いも押さえておく
どちらも「空」だが、性質が違う
空Listを返すとき、よく使うのがこの2つです。
Collections.emptyList(); // 不変(変更不可)の空List
new ArrayList<>(); // 変更可能な空List
Java空List安全取得では、基本的に Collections.emptyList() を使うのがおすすめです。
理由は二つあります。
一つ目は、「共有しても問題ないから」です。Collections.emptyList() は中身が変わらないので、
どこに渡しても安全です。
二つ目は、「“ここでは追加しない前提”がはっきりするから」です。emptyIfNull の戻り値に対して add しようとすると例外になるので、
「ここで追加するのは設計ミスだ」とすぐに気づけます。
List<String> safe = ListUtils.emptyIfNull(null);
safe.add("X"); // UnsupportedOperationException
Javaもし「呼び出し側で add したい」ケースなら、emptyIfNull の後で明示的に new ArrayList<>(safe) すればよい、
という分離ができます。
実務での「空List安全取得」の使いどころ
外部ライブラリや古いコードとつなぐときの“防波堤”
外部ライブラリや、昔の自前コードは、
平気で「該当なしなら null を返す」メソッドを持っていたりします。
そういうメソッドを直接使うのではなく、
必ず空List安全取得を挟むようにすると、安全な境界線を引けます。
List<String> raw = legacyApi.getNames(); // null かもしれない
List<String> names = ListUtils.emptyIfNull(raw); // ここから先は null ではない世界
Javaこの「境界で正規化する」という考え方は、
業務システム全体の安定性を上げるうえで、とても大事な感覚です。
まとめ:空List安全取得で身につけてほしい感覚
空List安全取得は、単に「NPE を避ける小技」ではなく、
「null を“空”にそろえて、世界をシンプルにする」 ためのユーティリティです。
null なら Collections.emptyList() を返す emptyIfNull を用意する。
List を返すメソッドは、原則として null ではなく空Listを返す設計にする。
空Listには不変のもの(Collections.emptyList())を使い、「ここでは追加しない前提」を明確にする。
外部や古いコードとの境界で「null → 空List」に正規化し、内側の世界をシンプルに保つ。
もしあなたのコードのどこかに、
List<String> list = xxx();
if (list != null) {
...
}
Javaというパターンが何度も出てきているなら、
それを一度「空List安全取得+空Listを返す設計」に置き換えられないか、眺めてみてください。
その小さな整理が、
「null に振り回されない、安定したコレクション処理を書けるエンジニア」への、
確かな一歩になります。

