Java 8 都快 12 岁了,Optional<T> 确实还是“半红不紫”,真实项目里你打开一个 2025 年的 Spring Boot 代码库,十有八九还是满屏 if (obj != null),真正用好 Optional 的团队屈指可数。到底卡在哪?下面把真实原因按“血泪严重程度”排一下序,都是我这几年在国内大厂、中厂、创业公司踩坑 + 面试 500+ 候选人总结出来的:
1. 生态和老项目惯性(罪魁祸首,占 60%)
- 99% 的公司项目都是 2014–2018 年用 Java 8 开的,那时候大家根本没搞懂 Optional,直接照抄以前的 null 判断写法。
- Spring、MyBatis、Jackson、Lombok 这些主流框架到 2022 年才开始部分支持 Optional(比如 @RequestParam Optional),之前全都是返回 null。
- 老项目改 Optional 成本极高:一个 UserService 里几百个 null 判断,你敢全换成 Optional 吗?代码审查直接被打回来。
2. 团队平均水平问题(占 25%)
真实对话现场:
// 2025年某银行项目真实代码
public User getUser(Long id) {
if (id == null) return null;
User user = userMapper.selectById(id);
return user; // 直接返回 null,没人想 Optional
}
// 面试时问:为什么不用 Optional?
候选人回答(原话):
“听说 Optional 有性能损耗”
“Optional 不能序列化吧?”
“我们 leader 说 Optional 看起来很装”
国内大部分 Java 程序员其实根本没认真读过《Effective Java》第 55 条(慎用 Optional),只在网上看到“Optional 不是为字段设计的”“Optional 序列化有坑”这类只言片语,就彻底放弃了。
3. 误解和真实痛点(占 10%)
常见误解 vs 真相:
| 误解 | 真相 |
|---|---|
| Optional 有性能损耗 | 只有创建时多一个对象,几乎可以忽略,和 new 一个异常比差远了 |
| Optional 不能序列化 | Java 8/9 确实有问题,但 Java 10+ 已修复,Jackson 2.9+ 也完美支持 |
| Optional 能替代 null 检查 | 它从来不是为了消灭所有 null,而是为了明确表达“这里可能为空” |
| Optional 滥用才真正恶心(Optional> 见过吗?) |
4. 真正用得好的人都在干嘛?
我见过少数用得风生水起的公司(阿里部分团队、字节新项目、少数独角兽)是这么玩的:
// 2025 年少数优秀团队写法
public Optional<User> findUser(Long id) { ... }
userService.findUser(id)
.map(User::getProfile)
.map(Profile::getAvatar)
.orElse(DEFAULT_AVATAR);
// Controller 层
@GetMapping("/user/{id}")
public ResponseEntity<UserDTO> get(@PathVariable Long id) {
return userService.findUser(id)
.map(UserDTO::from)
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
写成这样的人,通常都是:
- 2020 年以后入职的 95 后
- 看过《Java 8 实战》或《Modern Java in Action》
- 公司有代码规范强制“返回值明确为空时必须用 Optional”
5. 2025 年的现状总结
| 场景 | Optional 使用率 | 备注 |
|---|---|---|
| 新项目(2023+) | 60–80% | 尤其是 Kotlin 转 Java 的团队 |
| 传统大厂维护项目 | <10% | 改不动,也不敢动 |
| 创业公司/小团队 | 30–50% | 看技术 leader 个人喜好 |
| 外包/银行/政府项目 | 几乎为 0 | 写 null 判断写到 60 岁 |
一句话结尾:
Optional 不是没人用,是“能用好它的人太少,而项目又太老”。
除非哪天 Java 30 把 null 彻底干掉(像 Kotlin 那样),否则 Optional 永远都会是“看起来很美,用起来真麻烦”的代表。
你所在团队现在 Optional 用得怎么样?是彻底放弃,还是只在特定场景用?欢迎来吐槽真实比例~