Optional.of / ofNullable の役割をざっくりつかむ
Optional を「値を入れる箱」と考えると、Optional.of と Optional.ofNullable は
「箱に値を入れるときの入口が2種類ある」
と思ってください。
Optional.of(value)
「value は絶対に null ではないはずだ」と宣言するときに使う入口。
Optional.ofNullable(value)
「value は null かもしれない」と認めたうえで使う入口。
この2つを使い分けることで、
ここは null が来たら絶対ダメ
ここは null が来ても“空の Optional”にきちんと変換する
という意図をコードで表現できます。
Optional.of(value):null お断りの「厳しい入口」
null を入れようとすると即例外
Optional.of は、「ここには 絶対に null を渡してはいけない」という前提で使います。
Optional<String> opt = Optional.of("hello");
System.out.println(opt.isPresent()); // true
Java中身は "hello" を持った Optional になります。
一方で、null を渡すとどうなるか。
String s = null;
Optional<String> opt = Optional.of(s); // 実行時に NullPointerException
JavaOptional.of(null) は、その場で NullPointerException を投げます。
ポイントは、「Optional の中身を取り出すとき」ではなく、
「Optional を作る瞬間に」例外になることです。
どんなときに使うのが正しいか
「この値は、論理的に null のはずがない」と自信を持てる場所で使います。
例えば、必須フィールドを持つ不変オブジェクトを作るときに、
コンストラクタで null チェックをした結果、「ここまで来たら絶対 null ではない」と言える値などです。
public class User {
private final String name;
private final Optional<String> nickname;
public User(String name, String nickname) {
if (name == null) {
throw new IllegalArgumentException("name は必須");
}
this.name = name;
// nickname は null でもよい → Optional に包む
this.nickname = Optional.ofNullable(nickname);
}
public Optional<String> nickname() {
return nickname;
}
}
Javaこの例では、name は null 禁止(そもそも Optional にしてない)、nickname は null 許可 → Optional.ofNullable で包んでいるので、Optional.of は使っていません。
もし、内部で
「すでに null チェック済みで、ここに来る値は絶対 null じゃない」
と分かりきっているなら、Optional.of(nonNullValue) を使うと
「ここに null 渡したらバグだよ」という意思表示になります。
Optional.ofNullable(value):null かもしれない値を包む「安全な入口」
null なら empty に、それ以外なら of(value) に
Optional.ofNullable は、渡した値が
null でなければ Optional.of(value) と同じ
null なら Optional.empty() を返す
という、「両方に対応した安全な入口」です。
String s1 = "hello";
String s2 = null;
Optional<String> opt1 = Optional.ofNullable(s1);
Optional<String> opt2 = Optional.ofNullable(s2);
System.out.println(opt1.isPresent()); // true(中身あり)
System.out.println(opt2.isPresent()); // false(empty)
JavaofNullable のおかげで、「null の可能性がある値」を例外なしで Optional に包めます。
典型的な使いどころ:null を返す古い API を Optional に変換
既存のコードやライブラリには、「見つからなかったら null」を返すメソッドがたくさんあります。
User user = legacyFindUser(id); // 見つからないと null
Javaこれを Optional で扱いたいときに、ofNullable が活きてきます。
Optional<User> optUser = Optional.ofNullable(legacyFindUser(id));
Javaこれで、
見つかったとき → Optional.of(user) と同じ(中身あり)
見つからないとき → Optional.empty()(中身なし)
という状態になります。
あとは呼び出し側で、
optUser.ifPresent(user -> System.out.println(user.getName()));
String name = optUser.map(User::getName).orElse("ゲスト");
Javaのように、「無い場合も考えたコード」が書きやすくなります。
of / ofNullable を間違えるとどう危険か(ここをしっかり)
「とりあえず of を使う」は危険な癖
よくある悪いパターンが、「とりあえず全部 of で包む」です。
String s = legacyApi(); // 実は null の可能性あり
Optional<String> opt = Optional.of(s); // ここで NPE になるかも
Javaof を使うなら、「ここに null が来るはずがない」という確信が必要です。
それがないなら、問答無用で ofNullable を使うべきです。
「何でも ofNullable」も、意図がぼやける
逆に、何でもかんでも ofNullable にしてしまうと、
「本来 null が来るべきではないところ」まであいまいになります。
例えば、本来必ず存在するはずの設定値。
String baseUrl = loadConfig("baseUrl"); // 絶対入っている設定のはず
Optional<String> opt = Optional.ofNullable(baseUrl);
Java設定ファイルがおかしくて null になってしまった場合、opt は empty になってしまい、その後のコードで
String url = opt.orElse("http://localhost/");
Javaのように「適当に補われてしまう」かもしれません。
本来は、「設定が無いのはバグ」として、早めに気づいて落ちてほしい場面です。
そういうところでは、むしろ Optional.of(baseUrl) を使い、
null が来た瞬間に例外で気づいたほうが安全なことも多いです。
「どっちを使うか」を決めるシンプルな基準
自分への問いかけはこれで十分
値を Optional に包むとき、こう自問すると決めやすくなります。
この値は、論理的に null ありえる?ありえない?
ありえない → Optional.of(value)
ありえる → Optional.ofNullable(value)
「ありえるかどうか」が分からないときは、
一度型の設計と仕様を見直した方がいいサインです。
コードでの使い分けの雰囲気
外部APIや DB / ファイルからの読み出し結果
→ null の可能性が高いので、ofNullable で包むことが多い
自分で new したオブジェクトや、事前に null チェックした値
→ ここまでのロジックが正しければ null にならないはずなので、of を使ってもよい場面がある
というくらいの感覚から始めてかまいません。
まとめ:Optional.of / ofNullable をどう意識すればいいか
最後に、初心者向けにイメージを固定しておきます。
Optional.of(value) は
「value は絶対 null じゃない」という強い宣言。
もし null を渡すと、その場で NPE になって「設計ミス・バグ」を教えてくれる厳しい入口。
Optional.ofNullable(value) は
「value は null かもしれない」と認めたうえで、
null のときは Optional.empty() に変換してくれる、安全な入口。
コードを書くときは、
この値、本当に null の可能性ある?
あるなら ofNullable、ないなら of
と毎回意識するだけで、「なんとなく null」が減り、
「無い可能性」をちゃんと設計に取り込んだ、強いコードに近づいていきます。
