Optional<T> (Java 8+) は値を持つ場合と持たない場合がある容器です。nullを返す代わりに「値が存在しないかもしれない」を明示的に表現する方法です。呼び出し側が空のケースを考慮することを強制することで、恐ろしいNullPointerException(NPE)を防ぐのに役立ちます。
問題: nullとNPE
java
User {
userMap.get(id);
}
findUser();
u.getName();
Null戻り値は無視しやすく、その結果生じるNPE — 「10億ドルの誤り」 — はJavaで最も一般的なバグの1つです。
// ✅ the return type ITSELF signals "might be absent" — callers must handle it
public Optional<User> findUser(String id) {
return Optional.ofNullable(userMap.get(id));
}
今、シグネチャは不在を明示的に表現し、コンパイラが推奨するAPIは呼び出し側に空のケースに対処することを促します。
Optional<String> a = Optional.of("hi"); // value present (throws if you pass null)
Optional<String> b = Optional.empty(); // explicitly absent
Optional<String> c = Optional.ofNullable(x); // present if x != null, else empty
Optional<User> user = findUser("123");
// provide a fallback
User u = user.orElse(defaultUser);
User u2 = user.orElseGet(() -> createDefault()); // lazy fallback
User u3 = user.orElseThrow(() -> new NotFoundException());
// run code only if present
user.ifPresent(u -> System.out.println(u.getName()));
// transform without unwrapping (chainable, null-safe)
String name = user.map(User::getName).orElse("Unknown");
String city = user.map(User::getAddress).map(Address::getCity).orElse("N/A");
関数型メソッド(map、filter、orElse、ifPresent)により、値を安全に変換し、ネストされたnullチェックなしに値を取得し、チェーンすることができます。
// ❌ defeats the purpose — get() throws if empty, like dereferencing null
if (user.isPresent()) {
User u = user.get(); // verbose AND risky if you forget isPresent()
}
// ✅ use orElse/map/ifPresent instead
// ❌ don't use Optional for fields or method parameters — it's designed for RETURN types
// ❌ never return null from a method that returns Optional
OptionalはJavaのnullに関連するバグ問題に対処するためのツールで、不在の可能性を型システムで明示的にします — サイレントなNPEを処理されるケースに変えます。
主な意図された用途は、値を生成しない可能性のあるメソッドの戻り型として機能します。そこでは空のケースの考慮を文書化して強制し、その関数型メソッド(map、orElse、ifPresent)により、クリーンで null安全なチェーーンが可能になります。
正しい使い方を理解し、アンチパターン(get()を無分別に呼び出す、フィールド/パラメータに使う、nullを返す)を理解することは、より堅牢で自己文書化されたコードとNPEが少ないコードにつながります。これが、モダンJavaでベストプラクティスツールであり、一般的なインタビュー質問である理由です。