Java 逆引き集 | null/Optional の使い分け — NPE 回避、意図の明示

Java Java
スポンサーリンク

null/Optional の使い分け — NPE 回避、意図の明示

Javaでよくあるバグの一つが NullPointerException (NPE)
「変数が null なのにメソッドを呼んでしまった」ことで発生します。これを避けるために、Java 8 以降では Optional が導入されました。
「値があるかもしれない/ないかもしれない」を明示的に表現できる便利な仕組みです。


null の基本と問題点

String name = null;
System.out.println(name.length()); // NPE発生!
Java
  • 問題: null をそのまま扱うと、呼び出し側が「値がある前提」でコードを書きがち。
  • 対策: null チェックを必ず入れる。
if (name != null) {
    System.out.println(name.length());
} else {
    System.out.println("未設定です");
}
Java

👉 null は「値がない」ことを表すが、チェック漏れでNPEが起きやすい。


Optional の基本

宣言と生成

Optional<String> opt = Optional.of("Tanaka");       // 値あり
Optional<String> empty = Optional.empty();          // 値なし
Optional<String> maybe = Optional.ofNullable(null); // 値あり/なし両対応
Java

値の取り出し

String name = opt.get(); // 値がないと NoSuchElementException
Java

👉 直接 get() は危険。安全な取り出し方法を使う。

安全な取り出し方法

// 値があれば処理
opt.ifPresent(n -> System.out.println(n.toUpperCase()));

// 値がなければデフォルト
String result = opt.orElse("Unknown");

// 値がなければ計算して返す
String result2 = opt.orElseGet(() -> "Default");

// 値がなければ例外を投げる
String result3 = opt.orElseThrow(() -> new IllegalArgumentException("値なし"));
Java

null と Optional の使い分け指針

  • null を使う場面
    • フィールドの初期値(Javaの仕様で自動的に null になる)。
    • レガシーAPIやフレームワークとの互換性。
    • パフォーマンス重視で Optional を避けたい場面。
  • Optional を使う場面
    • メソッドの戻り値: 「値があるかもしれない/ないかもしれない」を明示したい。
    • API設計: 呼び出し側に「nullチェック必須」を強制したい。
    • 意図の明示: 「必ずある値」なら Optional ではなくプリミティブ/参照型を返す。

👉 フィールドや引数には null、戻り値には Optional が基本指針。


例題で練習

例題1: ユーザー検索(Optionalで安全に)

class User {
    String name;
    User(String name) { this.name = name; }
}

Optional<User> findUser(String id) {
    if ("001".equals(id)) return Optional.of(new User("Sato"));
    return Optional.empty();
}

// 呼び出し側
Optional<User> u = findUser("002");
u.ifPresent(user -> System.out.println(user.name));
Java

👉 「見つからない可能性」を Optional で表現。


例題2: null を返すレガシーAPIとの比較

// レガシーAPI
User findUserLegacy(String id) {
    if ("001".equals(id)) return new User("Sato");
    return null; // 見つからないときは null
}

// 呼び出し側
User u = findUserLegacy("002");
if (u != null) System.out.println(u.name);
Java

👉 null の場合は呼び出し側がチェック必須。


例題3: デフォルト値を返す

Optional<String> nickname = Optional.ofNullable(null);
String display = nickname.orElse("Guest");
System.out.println(display); // Guest
Java

👉 Optionalなら「なければこれ」と明示できる。


テンプレート集

Optional を返すメソッド

Optional<Type> findSomething(String key) {
    if (条件) return Optional.of(値);
    return Optional.empty();
}
Java

呼び出し側の安全な利用

Optional<Type> result = findSomething("key");
result.ifPresent(v -> System.out.println(v));
Type value = result.orElse(defaultValue);
Java

null を返すメソッド(レガシー)

Type findLegacy(String key) {
    if (条件) return 値;
    return null;
}
Java

まとめと次の一歩

  • null: 古くからある「値なし」の表現。チェック漏れでNPEが起きやすい。
  • Optional: 「値がある/ない」を明示できる。戻り値に使うと安全。
  • 指針: フィールドや引数には null、戻り値には Optional。

👉 練習課題として「商品検索API」を作り、商品が見つかれば Optional<Product> を返し、見つからなければ Optional.empty() を返すコードを書いてみると、業務ロジックに直結した理解が深まります。

タイトルとURLをコピーしました