本文目录导读:

当然可以!下面通过一个实际案例,我会带你一步一步学会如何使用 Optional 避免空指针异常,并写出更优雅、安全的代码。
案例背景
假设我们要实现一个用户服务:根据用户ID查询用户,然后获取用户的 配送地址的城市名。
典型“问题代码”(容易空指针)
public class UserService {
public String getCityByUserId(Long userId) {
User user = userRepository.findById(userId);
// user 是 null —— 空指针!
Address address = user.getAddress();
// address 是 null —— 空指针!
return address.getCity();
}
}
这段代码在 user、address 或 city 为 null 时,都会抛出 NullPointerException。
第一步:用 Optional 改造查询结果
让 findById 返回 Optional<User>(这是最佳实践):
public Optional<User> findById(Long userId) {
// ... 实际从数据库查询,可能返回 null
return Optional.ofNullable(数据库返回的对象);
}
第二步:用 Optional 链式操作避免嵌套空检查
public String getCityByUserId(Long userId) {
return userRepository.findById(userId) // Optional<User>
.map(User::getAddress) // Optional<Address>
.map(Address::getCity) // Optional<String>
.orElse("未知城市"); // 如果任意一步为null,返回默认值
}
核心原理:
map方法:如果当前 Optional 有值,则执行函数并返回新 Optional;如果当前 Optional 为空,则直接返回空 Optional,不会执行函数 → 自然不会调用 null 的方法。orElse:当最终 Optional 为空时,提供默认值。
第三步:更复杂的场景 + 异常处理
如果遇到 null 时想抛出自定义异常而不是返回默认值:
public String getCityByUserIdOrThrow(Long userId) {
return userRepository.findById(userId)
.map(User::getAddress)
.map(Address::getCity)
.orElseThrow(() -> new RuntimeException("用户或地址信息不完整"));
}
完整示例对比
| 方式 | 代码 | 风险 |
|---|---|---|
| ❌ 传统方式 | user.getAddress().getCity() |
每一步都可能 NPE |
| ✅ 使用 Optional | .map(User::getAddress).map(Address::getCity).orElse("默认") |
安全、简洁 |
- 返回 Optional 而不是 null:方法签名明确告诉调用者“可能没有值”。
- 多用
map/flatMap:优雅地处理链式调用。 - 用
orElse/orElseGet/orElseThrow处理无值情况:避免if (x != null)嵌套。 - 不要滥用:Optional 主要用于返回值,不要用在字段、方法参数或集合中。
思考题
你会怎么用 Optional 处理下面这个更复杂的情况?
// 现有代码:潜藏多个 NPE String countryName = user.getCompany().getAddress().getCountry().getName();
期待你的答案! 可以用 map 链式调用一行搞定。
学会了就点个赞吧 😊
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播