この記事でわかること
Map.of("A", null) のあるコードを読み、println まで進むかを判断します。続けて、任意項目が未入力のときに Map.of と HashMap をどう使い分けるかを確認します。
このページのクイズに進む。コードを見て、println まで実行されるか考えてください。


Java 9以降では、少数の固定データを簡潔に作るためにMap.ofを使えます。テストデータや区分値の対応表を作るときに使えます。任意項目が未入力の場合は、渡す値がnullになることがあります。
特に、画面入力や設定ファイルから取得した値をそのままMap.ofへ渡すコードは、正常データでは動いても任意項目が未入力のときだけ失敗します。APIの仕様と業務上のnullの意味を分けて考えましょう。
この記事のポイント
- Mapの生成とgetのどちらが先に実行されるか
- 固定の対応表と任意入力をどう扱い分けるか
まずはJavaクイズで実行順を考える

Map<String, String> values =
Map.of("A", null);
System.out.println(values.get("A"));答えはNullPointerExceptionです。Map.ofはキーにも値にもnullを許可せず、printlnより前の作成処理で例外になります。

クイズと解説のコードを手元で試す
クイズの例外、HashMapの出力、任意項目の扱い、変更できるコピーを確認できます。本文で省略したクラスやJUnitの設定も収録しています。JDK 17とMaven 3.9系を用意し、展開先で mvn test を実行してください。
例外はgetではなくMap作成時に発生する
コードを上から追うと、最初にMap.of("A", null)が評価されます。この呼び出しがMapを返せないため、変数valuesへの代入も、後続のgetも実行されません。障害ログの行番号もMap.ofの行を指します。
String value = null;
Map<String, String> map = Map.of("A", value);
// ここでNullPointerException『getしたらnullになった』と誤認すると、containsKeyやObjects.requireNonNullを後段へ足しても直りません。スタックトレースの先頭と評価順を確認し、例外が起きた行を正しく特定します。
Map.ofがnullを許可しない理由
Map.ofで作るMapは、作成後に内容を変更しない小さな固定Mapです。nullを禁止することで、『キーがない』と『値がnull』の曖昧さを持ち込まず、要素の存在を明確にしています。
これはすべてのMapがnullを禁止するという意味ではありません。Mapはインターフェースであり、nullを許可するか、変更できるか、スレッドセーフかは実装や生成方法によって異なります。変数型がMapでも契約は同じではありません。
Map.ofの主な特徴
- nullキーを渡せない
- null値を渡せない
- put・remove・clearで変更できない
- 同じキーを2回指定できない
- 要素の走査順を業務仕様として当てにしない
HashMapならnullを入れられる
HashMapは1つのnullキーと複数のnull値を許可します。そのため次のコード自体は動きます。
Map<String, String> map = new HashMap<>();
map.put("A", null);
System.out.println(map.get("A")); // null
System.out.println(map.get("B")); // nullただし、Aは登録済みnull、Bは未登録なのに、getの戻り値はどちらもnullです。区別が必要ならcontainsKeyを使います。技術的にnullを入れられることと、業務設計として入れるべきことは別です。
設定値やDTOからMap.ofを作るときの注意
固定の文字列だけでMap.ofを作る場合はnullになりません。危険なのは、外部から取得した値を直接渡す場合です。任意入力、DBのNULL、環境変数未設定、JSONの項目不足などがnullの入口になります。
Map<String, String> attributes = Map.of(
"department", userForm.getDepartment(),
"extension", userForm.getExtension());内線番号が任意項目なら、未入力時に失敗します。null項目をMapから除外する、空文字へ変換する、専用DTOを使う、必須入力にするなど、仕様に合う対応を選びます。とりあえず空文字にする修正は、未設定と空文字の意味が同じ場合だけにします。
変更したいなら最初から別のMapを選ぶ
Map.ofで作った後にputするとUnsupportedOperationExceptionになります。初期値を簡潔に書きつつ後で変更したいなら、HashMapのコンストラクタへ渡して可変コピーを作ります。
Map<String, String> map = new HashMap<>(
Map.of("status", "NEW"));
map.put("owner", "U001");一方、固定の区分表や定数として使うなら、変更できない方が安全です。『念のためHashMap』にすると、後続処理が誤って書き換えても気付きにくくなります。ライフサイクルから可変・不変を選びます。
nullを持たせない設計を検討する
Mapの値にnullを入れると、未取得、該当なし、入力なし、取得失敗など複数の意味が混ざりやすくなります。必要ならOptional、状態を持つDTO、enum、結果クラスで意味を分けます。
record UserAttribute(String department, Optional<String> extension) {}
UserAttribute attribute = new UserAttribute(
department, Optional.ofNullable(extension));Optionalをフィールドに使うかはプロジェクト方針もあります。大切なのはOptionalそのものではなく、『このnullは何を意味するか』を型や契約で説明できることです。
JUnitで作成時の契約を確認する
ライブラリ仕様をそのままテストする必要はありませんが、外部入力から固定Mapを作る自作メソッドには、任意項目null時の期待動作を残します。
@Test
void 任意項目がnullならMapから除外する() {
Map<String, String> actual = mapper.toAttributes(
new UserForm("営業", null));
assertEquals("営業", actual.get("department"));
assertFalse(actual.containsKey("extension"));
}例外にする設計なら、どの例外型とエラーコードに変換するかをテストします。NullPointerExceptionが偶然そのまま500エラーになる状態は、利用者にも運用者にも意図が伝わりません。
現場レビューでよくある指摘
Map.ofのレビューでは、短く書けているかより、入力がnullにならない契約と作成後に変更しない意図が成立するかを見ます。
// レビューコメント例
extensionは任意入力なのでnullになります。Map.ofはnullを許可しません。
未設定項目を除外するか、専用DTOで表現してください。
// レビューコメント例
このMapは後続でputしています。Map.ofの戻り値は変更できないため、
最初からHashMapを使うか、可変コピーを作ってください。
// レビューコメント例
値nullとキー未登録を区別する仕様でしょうか。
HashMapへnullを入れる前に、状態の表現方法を整理してください。NullPointerExceptionへ場当たり的なnullチェックを足す前に、どの入力がnullになり、Mapにその状態を保持する必要があるか確認します。作成時と利用時の契約をそろえるのが先です。
提出前のセルフチェック
レビュー前に確認すること
- Map.ofへ渡す値がnullにならないか
- 例外発生行を作成時点として確認したか
- 作成後にputやremoveをしていないか
- キー未登録と値nullを区別する必要があるか
- 固定Mapとして不変にする意図があるか
- 同一キーや順序へ依存していないか
- 任意入力・DB NULL・環境変数未設定をテストしたか
Javaコレクションを体系的に学ぶ参考書
Mapは生成方法ごとにnull、変更可否、順序の契約が異なります。コレクションの基本をまとまって確認すると、短いファクトリメソッドを安全に選べます。
スッキリわかるJava入門 第5版
変数・条件分岐から、クラスの基本まで学ぶ一冊。
豊富な図とサンプルで、変数、条件分岐、クラス、例外処理まで順番に学べます。Javaの最初の教科書を探している人向けです。
- Javaを基礎から体系的に学びたい
- Java 25 LTS対応の入門書を選びたい
当サイトはAmazonアソシエイト・プログラムの参加者です。価格・在庫・配送条件はAmazonでご確認ください。
この記事とあわせて読みたい
まとめ
Map.ofはnullのキーと値を許可しないため、nullを渡すとMap作成時点でNullPointerExceptionになります。また、作成したMapはputやremoveで変更できません。
HashMapならnullを格納できますが、未登録との区別が必要です。入力がnullになる理由とMapのライフサイクルを確認し、不変Map、可変Map、専用DTOのどれが意図を表せるか選んでください。



