Tianyi's Blog Tianyi's Blog
首页
  • 计算机网络
  • 操作系统
  • 计算机科学
  • Nginx
  • Vue框架
  • 环境配置
  • Java
  • JVM
  • Spring框架
  • Redis
  • MySQL
  • RabbitMQ
  • Kafka
  • Mirror Sites
  • Dev Tools
  • Docker
  • Jenkins
  • Scripts
  • Windows
  • 科学上网
  • 旅行
  • 网站日记
  • 软件
  • 电子产品
  • 杂野
  • 分类
  • 友情链接
GitHub (opens new window)

Tianyi

一直向前,永不停止
首页
  • 计算机网络
  • 操作系统
  • 计算机科学
  • Nginx
  • Vue框架
  • 环境配置
  • Java
  • JVM
  • Spring框架
  • Redis
  • MySQL
  • RabbitMQ
  • Kafka
  • Mirror Sites
  • Dev Tools
  • Docker
  • Jenkins
  • Scripts
  • Windows
  • 科学上网
  • 旅行
  • 网站日记
  • 软件
  • 电子产品
  • 杂野
  • 分类
  • 友情链接
GitHub (opens new window)
  • Java

    • web基础
    • 策略模式
    • Java基础语法
    • JavaWeb-Base
    • Optional处理空指针,这几招你会了吗?
      • 一、创建Optional的正确姿势
        • 1. 别踩坑的of方法
        • 2. 最常用的ofNullable
      • 二、安全取值的几种姿势
        • 1. 保底值大法:orElse
        • 2. 延迟加载:orElseGet
        • 3. 抛异常终结者
      • 三、链式操作真香警告
        • 1. 安全转换:map
        • 2. 避免套娃:flatMap
      • 四、这几个坑千万别踩
        • 1. 不要用isPresent()+get()
        • 2. 别用在参数和字段上
        • 3. 空集合别用Optional
      • 五、实际开发中的小技巧
        • 1. 和Stream配合使用
        • 2. 记录日志更方便
      • 六、到底该不该用Optional?
    • 并发编程的艺术
    • 并发编程工具
    • 一个简单的 web 服务器实例
    • 小笔记-线程池
    • 小笔记-JUC入门
  • Golang

  • JVM的奇妙世界

  • Spring

  • Spring增强封装

  • Redis

  • MySQL

  • RabbitMQ

  • Kafka

  • 分享

  • 后端
  • Java
tianyi
2024-02-03
目录
一、创建Optional的正确姿势
1. 别踩坑的of方法
2. 最常用的ofNullable
二、安全取值的几种姿势
1. 保底值大法:orElse
2. 延迟加载:orElseGet
3. 抛异常终结者
三、链式操作真香警告
1. 安全转换:map
2. 避免套娃:flatMap
四、这几个坑千万别踩
1. 不要用isPresent()+get()
2. 别用在参数和字段上
3. 空集合别用Optional
五、实际开发中的小技巧
1. 和Stream配合使用
2. 记录日志更方便
六、到底该不该用Optional?

Optional处理空指针,这几招你会了吗?

# Optional处理空指针,这几招你会了吗?

作为一个Java开发者,谁没被空指针坑过呢?以前我们总得写一堆if(xxx != null),代码又臭又长。自从Java 8出了Optional,用好了真的能少写很多防御代码。今天就和大家聊聊怎么把这玩意儿用顺手了。

# 一、创建Optional的正确姿势

ofNullable() 并非魔法,它只是将 null 值封装到 Optional 对象中。真正的价值在于后续链式方法带来的安全操作空间。

# 1. 别踩坑的of方法

// 千万别这么写!传null直接爆炸
Optional<String> opt = Optional.of(null); 
1
2

这个of()方法就像个暴脾气的老哥,只要你敢传null,它立马甩你一个空指针异常。只有在100%确定对象不为null的时候才能用它。

# 2. 最常用的ofNullable

// 这才是正确打开方式
Optional<User> userOpt = Optional.ofNullable(userService.findById(123));
1
2

不管拿到的user是不是null,这个方法都能稳稳接住。相当于给可能为null的值套了个保护壳。

# 二、安全取值的几种姿势

# 1. 保底值大法:orElse

// 有值拿值,没值拿默认
User user = userOpt.orElse(new User("匿名用户")); 
1
2

适合默认对象创建成本不高的场景。比如这里new一个默认用户,内存开销不大。

# 2. 延迟加载:orElseGet

// 只有需要时才创建默认用户
User user = userOpt.orElseGet(() -> {
    // 从数据库加载默认配置
    return defaultUserRepository.findByName("guest");
});
1
2
3
4
5

当默认对象构造比较费资源时(比如查数据库),一定要用这个!避免无谓的性能消耗。

# 3. 抛异常终结者

// 找不到就报错
Config config = configOpt.orElseThrow(() -> {
    throw new ServiceException("系统配置缺失");
});
1
2
3
4

把空值转换为业务异常,比直接抛NPE有意义多了。比如这里明确告诉调用方是配置缺失的问题。主要是这种书写方式真的太优雅了

# 三、链式操作真香警告

# 1. 安全转换:map

// 三级安全转换
String city = userOpt
    .map(User::getAddress) // 用户→地址
    .map(Address::getCity) // 地址→城市
    .orElse("未知地区");    // 保底值
1
2
3
4
5

不管哪个环节为null,都会自动跳转到保底值。相当于给每个get方法都加了空判断!

# 2. 避免套娃:flatMap

// 用户可能有地址,地址可能有坐标
Optional<Coordinate> coord = userOpt
    .flatMap(user -> user.getAddress()) // 返回Optional<Address>
    .flatMap(address -> address.getCoord());
1
2
3
4

当你的get方法本身就返回Optional时,用flatMap就不会出现Optional<Optional<...>>这种套娃结构了。

# 四、这几个坑千万别踩

# 1. 不要用isPresent()+get()

// 错误示范!
if(userOpt.isPresent()){
    User user = userOpt.get();
    // 一堆操作
}
1
2
3
4
5

这写法跟直接判null没区别,完全没发挥Optional的优势。应该用orElse系列方法替代。

# 2. 别用在参数和字段上

// 方法参数不要这样写
public void badExample(Optional<String> param){...} 

// 类字段也别用
class User {
    private Optional<String> name; // 大忌!
}
1
2
3
4
5
6
7

Optional是设计用来做返回值的,滥用反而会让代码变复杂。

# 3. 空集合别用Optional

// 返回空集合更直观
public List<Order> findOrders(){
    return Collections.emptyList();
}

// 比下面这种写法好
public Optional<List<Order>> findOrders(){...}
1
2
3
4
5
6
7
  • 空集合 本身可以很好地表达“没有数据”的含义,无需画蛇添足地用 Optional 包装。
  • 与 JPA 数据库的 API 设计思想一致,JPA 在查询不到数据时,通常返回空集合,而不是 null 或 Optional。

# 五、实际开发中的小技巧

# 1. 和Stream配合使用

// 过滤掉空值
List<String> names = users.stream()
    .map(user -> Optional.ofNullable(user.getName()))
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());
1
2
3
4
5
6

不过更推荐这样写:

List<String> names = users.stream()
    .map(User::getName)
    .filter(Objects::nonNull)
    .collect(Collectors.toList());
1
2
3
4

# 2. 记录日志更方便

userOpt.ifPresent(user -> {
    log.info("用户操作:{}", user.getName());
    auditService.record(user);
});
1
2
3
4

这种写法既安全又直观,不需要先判空再操作。

# 六、到底该不该用Optional?

用了两年Optional的老司机说句实在话:

该用的时候大胆用,但别强行用。适合的场景:

  • 明确可能返回null的方法返回值
  • 需要链式处理可能为null的对象时

不适合的场景:

  • 集合类(用空集合更好)
  • 简单的非空判断(直接if判断更直观)
  • 性能敏感的场景(Optional有对象创建开销)

最后记住:Optional是帮我们更优雅地处理null,不是用来消灭null的。关键还是要在写代码时对可能为null的地方保持敏感,结合业务场景选择最合适的处理方式。

完善页面 (opens new window)
JavaWeb-Base
并发编程的艺术

← JavaWeb-Base 并发编程的艺术→

最近更新
01
JDK
02-23
02
BadTasteCode && 优化
09-11
03
Gradle 实践操作指南及最佳实践
09-11
更多文章>
Theme by Vdoing | Copyright © 2021-2025 Tandy | 粤ICP备2023113440号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式