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("値なし"));
Javanull と 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);
Javanull を返すメソッド(レガシー)
Type findLegacy(String key) {
if (条件) return 値;
return null;
}
Javaまとめと次の一歩
- null: 古くからある「値なし」の表現。チェック漏れでNPEが起きやすい。
- Optional: 「値がある/ない」を明示できる。戻り値に使うと安全。
- 指針: フィールドや引数には null、戻り値には Optional。
👉 練習課題として「商品検索API」を作り、商品が見つかれば Optional<Product> を返し、見つからなければ Optional.empty() を返すコードを書いてみると、業務ロジックに直結した理解が深まります。
