Optional<T>(Java 8+)是一个容器,可能包含也可能不包含一个值——这是一种显式的方式来表示"一个值可能不存在",而不是返回 null。它通过强制调用者考虑空值情况来帮助防止可怕的 NullPointerException(NPE)。
问题:null 和 NPE
java
User {
userMap.get(id);
}
findUser();
u.getName();
Null 返回值很容易被忽视,由此产生的 NPE——"十亿美元的错误"——是最常见的 Java bug 之一。
// ✅ 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 相关的 bug问题的工具,通过在类型系统中使值缺失的可能性变得显式——将无声的 NPE 转变为需要处理的情况。
它的主要预期用途是作为可能不产生值的方法的返回类型,其中它文档化并强制考虑空值情况,其函数式方法(map、orElse、ifPresent)使得清晰的、null 安全的链式调用成为可能。
理解如何正确使用它——以及反面模式(不谨慎地调用 get()、用于字段/参数、返回 null)——会导致更健壮、自文档化的代码,NPE 更少,这就是为什么它既是最佳实践工具,也是现代 Java 中的常见面试话题。