中 基础
Optional用法#
一句话答案#
Optional是 JDK 8 引入的容器,用来显式表达”值可能为空”,通过map/filter/orElse/ifPresent链式处理,优雅规避 NPE;最佳实践是作返回值,不作字段和方法参数。
核心要点
1. 创建
Optional.of(value); // value 不能为 null,否则 NPE
Optional.ofNullable(value); // value 可为 null(推荐用于不确定的场景)
Optional.empty(); // 空容器java2. 取值与默认值
opt.get(); // 空时抛 NoSuchElementException —— 慎用!
opt.orElse(defaultVal); // 空则返回默认值(无论是否空都会求值)
opt.orElseGet(() -> compute()); // 空时才执行 supplier(惰性,推荐)
opt.orElseThrow(() -> new BizException()); // 空则抛指定异常java3. 链式处理(核心价值)
// 传统层层判空
String city = user != null && user.getAddr() != null ? user.getAddr().getCity() : "未知";
// Optional 链式
String city = Optional.ofNullable(user)
.map(User::getAddr)
.map(Addr::getCity)
.orElse("未知");javamap:值存在则转换,否则保持空。filter:值存在且满足条件才保留。flatMap:转换结果本身是 Optional 时用它避免嵌套Optional<Optional<>>。ifPresent(consumer):存在则消费。
4. 最佳实践与反模式
| ✅ 推荐 | ❌ 反模式 |
|---|---|
| 作方法返回值表达”可能无结果” | 作类字段(不可序列化、增内存) |
orElseGet 惰性求默认值 | isPresent()+get()(退化成判空) |
map 链式转换 | 直接 get() 不判空(等于没用) |
orElseThrow 表达业务异常 | 作方法参数(调用方还得包一层) |
面试回答(2分钟版)
Optional 是 JDK 8 引入的一个容器类,用来显式地表达一个值可能存在也可能为空,目的是从语法层面规避空指针异常,同时让”可能为空”这件事在 API 签名上变得明确。创建有三种方式:of 要求值非空否则直接抛异常,ofNullable 允许传 null,empty 是空容器。取值时最该避免的是直接调 get,因为空的时候会抛 NoSuchElementException,跟空指针没区别。推荐用 orElse 给默认值,或者 orElseGet 传一个 supplier 惰性求值——注意 orElse 不管空不空都会先把默认值算出来,orElseGet 只有空的时候才执行,性能更好。Optional 真正的价值在链式处理,配合 map、filter、flatMap 可以把传统层层判空的代码写成一条流畅的链,比如取用户地址里的城市,一路 map 下去最后 orElse 一个默认值,任何一环为空都安全短路。最佳实践方面:Optional 适合作方法返回值表达可能无结果,但不建议作类的字段,因为它没实现 Serializable 还增加内存,也不建议作方法参数,会让调用方很别扭。最大的反模式是用 isPresent 加 get,那等于把 Optional 又退化成了 if 判空,完全没发挥它的作用。
追问与易错
追问方向:
- “orElse 和 orElseGet 区别?”→ orElse 的默认值无论是否为空都会被求值;orElseGet 的 supplier 只在为空时执行,涉及昂贵计算时用 orElseGet
- “为什么不推荐 Optional 作字段?”→ 未实现 Serializable,序列化受限;每个字段多包一层对象增加内存;语义上字段为空用 null 即可
- “map 和 flatMap 区别?”→ map 的函数返回普通值会自动包成 Optional;若函数本身返回 Optional 用 flatMap 避免 Optional 嵌套
- “Optional 能彻底消除 NPE 吗?”→ 不能。误用 get 或对 Optional 本身为 null 仍会出问题,它只是工具不是银弹
- “Optional 是值类型吗?”→ 是基于值的类(value-based),不应对其做同步或用 == 比较
易错点:
- ❌
isPresent()+get()——退化成判空,应直接 map/orElse - ❌
Optional.of(可能为null的值)——会抛 NPE,不确定时用 ofNullable - ❌ 把 Optional 当字段或参数——只作返回值
- ❌ 昂贵默认值用 orElse——应用 orElseGet 惰性求值