Java 避免空指针的方法及Optional最佳实践
【一】避免空指针的通用方法
✅ 1️⃣ 设计阶段:避免产生 null
领域模型里避免「nullable」属性
构造函数里要求非空
✅ 示例
public User(String name) {
this.name = Objects.requireNonNull(name, "name must not be null");
}
✅ 2️⃣ 静态检查
注解
@Nonnull
,@Nullable
Checker Framework / ErrorProne / SpotBugs
✅ 示例
public String process(@Nonnull String input) { return input.trim(); }
✅ 3️⃣ 运行时保护
Objects.requireNonNull()
✅ 4️⃣ 语言级增强
Java 14+: 增强的 NPE 异常信息
默认开启(Java 16+)
-XX:+ShowCodeDetailsInExceptionMessages
✅ 输出示例
Cannot invoke "Address.getCity()" because "person.getAddress()" is null
✅ 5️⃣ Null Object 模式
避免返回 null,用无害对象表示「空行为」
✅ 示例
class NullLogger implements Logger {
public void log(String msg) { /* do nothing */ }
}
✅ 6️⃣ Optional
Java 8+ 的核心改进:明确表达「可能缺失」
✅ 语义
Optional 返回值 → 明确可为空
避免调用者遗漏 null 检查
✅ 基本用法
Optional<User> findById(String id) {
return Optional.ofNullable(repo.get(id));
}
【二】Optional 最佳实践
✅ ① 适用场景
✅ 用于方法返回值
表示查询、解析、计算 可能没有结果
✅ 示例
Optional<User> findUserById(String id);
❌ ② 不推荐场景
❌ 参数
void setUser(Optional<User> user); // 不推荐
✅ 用
void setUser(@Nullable User user);
❌ 类字段
class User {
Optional<Address> address; // 不推荐
}
✅ 用
class User {
@Nullable Address address;
}
然后在 getter 中返回 Optional
public Optional<Address> getAddress() {
return Optional.ofNullable(address);
}
❌ 集合
Optional<List<User>> getUsers(); // 不推荐
✅ 直接返回空集合
List<User> getUsers();
✅ ③ 创建 Optional
Optional.of(value) // value != null
Optional.ofNullable(value) // 允许 value 为 null
Optional.empty()
✅ ④ 消费值
optional.ifPresent(u -> sendEmail(u.getEmail()));
✅ ⑤ 默认值
String result = optional.orElse("default");
String lazy = optional.orElseGet(() -> computeDefault());
✅ ⑥ 抛异常
User user = optional.orElseThrow(() -> new NotFoundException());
✅ ⑦ 链式变换
Optional<Address> address = userOpt.map(User::getAddress); Optional<String> city = userOpt.map(User::getAddress).map(Address::getCity);
✅ ⑧ 过滤
optional.filter(u -> u.isActive())
✅ ⑨ Java 9+ 扩展
optional.or(() -> otherOptional);
optional.ifPresentOrElse( val -> process(val), () -> handleAbsent() );
✅ ⑩ 避免 get()
⚠️ 反模式
String s = optional.get(); // 潜在 NPE
✅ 推荐
optional.orElse(...) optional.orElseThrow(...)
总结
✅ 方法返回值 → Optional 表示「可无」
✅ 参数 → 不用 Optional,直接 @Nullable
✅ 字段 → 不用 Optional,用普通类型 + @Nullable
✅ 集合返回值 → 返回空集合,不要包 Optional
✅ 使用链式 map / flatMap / filter
✅ 消费时用 orElse / orElseThrow / ifPresent