JavaのOptional.of(null)でNullPointerExceptionになる原因とofNullableとの違いを解説する記事のアイキャッチ。

Java クイズ

JavaのOptional.of(null)でNullPointerExceptionになる原因|ofNullableとの違い

AIによる要約

Optional.ofはnullではない値だけを受け取り、nullを渡すと生成時点でNullPointerExceptionになります。後ろにorElseを書いていても到達しません。nullを「値なし」として扱う仕様ならOptional.ofNullableを使うと、nullはOptional.emptyへ変換されます。ただし、必須値の欠落までofNullableで隠すのは危険です。ofとofNullableはNPEを避けるために機械的に選ぶのではなく、その値にnullを許可する契約かどうかで使い分けます。

この記事は2026年9月1日分のX向けJavaクイズを詳しく解説したものです。問題と回答は本文内でも確認できます。

新人SE
新人SE
OptionalにしてorElseも書いたのに、NullPointerExceptionになりました。Optionalならnullを安全に扱えると思っていました。
ポンコツSE
ポンコツSE
Optional.ofへnullを渡すと、その場で例外になります。nullをemptyへ変換するのはofNullableです。

Optionalは「nullを入れても落ちない箱」ではありません。値が存在するかもしれない状態を、呼び出し側へ明示するための型です。作り方を間違えると、Optionalを使う前の生成部分でNullPointerExceptionになります。

特に、画面入力、CSV、外部API、Map#get、古いライブラリの戻り値など、nullが混ざる可能性のある値をOptional.ofへ渡すコードで起きます。目の前の例外だけを消すのではなく、そのnullが正常な未設定なのか、設計上あり得ない欠落なのかを確認することが重要です。

この記事のポイント

  • Optional.ofはnullを受け取れない
  • Optional.of(null)は生成時点でNullPointerException
  • 後ろのorElseには到達しない
  • ofNullable(null)はOptional.emptyになる
  • ofとofNullableは値の契約で使い分ける
  • Optionalを返すメソッドからnullを返さない

まずはXのJavaクイズを確認する

nullのnameをOptional.ofへ渡し、orElseでguestを指定したJavaコードの結果を問うクイズ画像。
nameがnullのとき、orElseのguestは使われるでしょうか。
String name = null;

Optional<String> value =
    Optional.of(name);

System.out.println(value.orElse("guest"));

答えはCのNullPointerExceptionです。例外が起きるのはorElseではなく、Optional.of(name)を実行した時点です。そのためSystem.out.printlnには到達しません。

答えはNullPointerException。Optional.ofはnullを許可せず、nullの可能性がある値にはOptional.ofNullableを使うと説明する画像。
ofNullableならnullをOptional.emptyへ変換できます。

Optional.of(null)はなぜ例外になるのか

Optional.ofは、nullではない値からOptionalを作るためのメソッドです。引数がnullでないことがAPIの前提であり、nullが渡されるとNullPointerExceptionを送出します。

Optional<String> present = Optional.of("Java");
System.out.println(present.get()); // Java

Optional<String> error = Optional.of(null);
// NullPointerException

これは不便な制約ではありません。Optional.of(value)と書いた場所は「ここではvalueが必ず存在する」という意思表示になります。もしnullが混ざれば、その契約が破られた場所ですぐに分かります。

反対に、Optionalの中へnullをそのまま保持することはできません。Optionalが表すのは「値があるpresent」か「値がないempty」のどちらかです。nullを保持した3つ目の状態はありません。

orElseを書いてもNullPointerExceptionを防げない

orElseは、すでに作成できたOptionalがemptyだった場合に代替値を返します。Optionalを作る途中で例外になった場合は動きません。

String name = null;
String result = Optional.of(name)
        .orElse("guest");

実行順は、Optional.of(name)でOptionalを作り、その戻り値に対してorElseを呼ぶ流れです。1段目でNullPointerExceptionになれば、2段目は呼ばれません。「orElseがあるからnullでも大丈夫」という読み方はできません。

例外が起きた行を先に確認する

スタックトレースがOptional.ofの行を指しているなら、orElseやgetの問題ではありません。Optionalを作る前の値がなぜnullなのかを追います。

Optional.ofNullableならnullをemptyへ変換する

nullが正常に入り得て、値なしとして扱いたい場合はOptional.ofNullableを使います。nullならOptional.empty()、nullでなければ値を持つOptionalを返します。

String name = null;

String result = Optional.ofNullable(name)
        .orElse("guest");

System.out.println(result); // guest

このコードではofNullableがemptyを返すため、orElseのguestが採用されます。nameがYujiなら、その値がそのまま返ります。

Optional.ofNullable("Yuji").isPresent(); // true
Optional.ofNullable(null).isEmpty();     // true

ofとofNullableの違い

メソッド引数が値引数がnull向いている場面
Optional.of値を持つOptionalNullPointerExceptionnullでないことが前提の内部値
Optional.ofNullable値を持つOptionalOptional.emptynullを未設定として扱う入力境界
Optional.empty引数なし常にempty値がないことを明示して返す

実行結果だけならofNullableの方が安全に見えます。しかし、必須の値がnullになったときまでemptyへ変換すると、本来早く気付くべき不具合が「値なし」の通常ルートへ流れます。

たとえばログイン済みユーザーID、保存済み注文の注文番号、必須設定値など、設計上nullにならない値ならOptional.ofで前提違反を早く検知する考え方があります。一方、検索結果、任意入力、外部連携の省略項目など、値がないことが正常ならofNullableが候補です。

何でもofNullableに変えればよいわけではない

NullPointerExceptionを見て、すべてのOptional.ofofNullableへ置き換える修正は危険です。例外は消えても、欠落した値を使った処理が静かにスキップされたり、デフォルト値で正常終了したように見えたりします。

// 必須の顧客コードがnullでもguestへ流れてしまう
String customerCode = Optional.ofNullable(order.getCustomerCode())
        .orElse("guest");

顧客コードが必須なら、デフォルト値へ置き換えるより、保存前の入力チェック、データ整合性、マッピング漏れを直すべきです。nullが正常な状態か、異常な状態かを決めないままOptionalで包むと、問題の場所を移動させるだけです。

レビューでは「この値はnullになり得ますか」だけでなく、「nullだった場合に処理を続けてよいですか」まで確認します。前者が技術的な可能性、後者が業務仕様です。

外部入力との境界でofNullableを使う例

古いAPIやMap#getなど、戻り値としてnullを使う既存仕様との境界では、ofNullableでOptionalへ変換すると、その後の処理でnullチェックを繰り返さずに済みます。

Optional<String> findHeader(
        Map<String, String> headers,
        String name) {
    return Optional.ofNullable(headers.get(name));
}

Map#getは、キーがない場合にnullを返します。このnullを境界でemptyへ変換すれば、利用側はOptionalとして扱えます。ただしMapがnull値を許可している場合、「キーがない」と「キーはあるが値がnull」を同じemptyにまとめてよいか確認が必要です。区別が必要ならcontainsKeyを使います。

外部APIのレスポンスでも同じです。任意項目ならemptyへ変換できますが、必須項目が欠けているなら連携エラーとして扱う方が適切です。ofNullableを置く位置は、外部仕様を内部の型へ変換する境界が分かりやすいでしょう。

Optionalを返すメソッドからnullを返さない

戻り値をOptionalにしたのに、値がない場合にnullを返す実装は避けます。呼び出し側はOptional自体がnullか、Optionalの中身がemptyかという二重の確認を要求されます。

// NG: Optional自体がnull
Optional<User> findUser(long id) {
    User user = repository.find(id);
    return user == null ? null : Optional.of(user);
}

// OK: 値なしはOptional.empty
Optional<User> findUser(long id) {
    return Optional.ofNullable(repository.find(id));
}

Optionalを返すというメソッド契約を採用したら、戻り値のOptional自体はnullにしません。値がなければOptional.empty()です。呼び出し側はorElseThrow、map、ifPresentなどで値なしを扱えます。

また、EntityやDTOの全フィールドをOptional型にする必要はありません。Optionalは主に戻り値で「値がない可能性」を伝える用途に向きます。フィールドやメソッド引数での採用は、シリアライズやフレームワーク対応も含め、チームの設計方針へ合わせます。

JUnitで値ありとnullを両方確認する

Optionalを作るメソッドでは、値がある場合だけでなくnullの場合の期待値もテストします。ofを使うなら例外、ofNullableを使うならemptyになることを明示します。

@Test
void ofはnullで例外になる() {
    assertThrows(NullPointerException.class,
            () -> Optional.of(null));
}

@Test
void ofNullableはnullをemptyにする() {
    Optional<String> result = Optional.ofNullable(null);
    assertTrue(result.isEmpty());
}

@Test
void ofNullableは値を保持する() {
    Optional<String> result = Optional.ofNullable("Java");
    assertEquals("Java", result.orElseThrow());
}

実際のServiceでは、emptyのときにデフォルト値、404、業務例外、処理スキップのどれになるかまでテストします。「NullPointerExceptionが出ない」だけでは、業務上正しい動作か判断できません。

現場レビューでよくある指摘

// レビューコメント例
nameがnullになる可能性があるため、Optional.ofの時点でNPEになります。
未設定を許可する仕様ならofNullableを使ってください。

// レビューコメント例
customerCodeは必須値の認識です。
ofNullableでemptyへ変換する前に、nullになる原因を確認したいです。

// レビューコメント例
Optionalを返すメソッドからnullが返っています。
値なしはOptional.emptyで統一してください。

// レビューコメント例
orElseはOptional生成後に呼ばれるため、
Optional.of(null)のNPEは防げません。

レビューで重要なのは、API名の置き換えだけを求めないことです。nullが発生する経路と、値なしを正常として扱うかを確認した上で修正案を出します。

提出前のセルフチェック

レビュー前に確認すること

  • Optional.ofへ渡す値が本当にnullにならないか
  • nullの場合にorElseまで到達しないと理解しているか
  • nullを正常な未設定として扱ってよいか
  • 必須値の欠落をofNullableで隠していないか
  • 外部入力との変換境界が明確か
  • Optionalを返すメソッドからnullを返していないか
  • empty時の業務動作を決めたか
  • 値ありとnullの両方をテストしたか
  • ログや例外に調査可能な情報が残るか

JavaのnullとOptionalを学ぶ参考書

Optionalは単独の便利メソッドとして覚えるより、null、例外、戻り値の契約、Stream APIと合わせて学ぶと使いどころを判断しやすくなります。チームの既存コードと公式API仕様を見比べてください。

書籍「スッキリわかるJava入門 実践編 第5版」の表紙
商品画像:Amazon.co.jp
PR Java基礎学習後の若手向け

スッキリわかるJava入門 実践編 第5版

中山 清喬 (著), 株式会社フレアリンク (監修)

基礎文法の次に必要な、現場寄りのJava知識を補う。

コレクション、ジェネリクス、ラムダ式、ストリームなど、業務コードで出会いやすい機能を入門編の次に学べます。

  • Java基礎の次に何を学ぶか迷っている
  • コレクションやStreamを整理したい

当サイトはAmazonアソシエイト・プログラムの参加者です。価格・在庫・配送条件はAmazonでご確認ください。

この記事とあわせて読みたい

まとめ

Optional.of(null)は、Optionalを作る時点でNullPointerExceptionになります。後ろにorElseを書いても到達しません。nullを値なしとして扱う仕様ならOptional.ofNullableを使い、nullをOptional.emptyへ変換します。

ただし、すべてをofNullableへ変えるのではなく、その値にnullを許可するかで選んでください。必須値の欠落は早く検知し、任意値や外部仕様のnullは境界でemptyへ変換します。Optionalを返すメソッド自体からnullを返さず、empty時の業務動作までテストします。

APIの正確な仕様は、OracleのOptional公式ドキュメントも確認してください。

-Java, クイズ