Java8 Optional 类的使用

本文最后更新于 2025年5月20日 14:24

传统的防止出现 NullpointerException异常的方法是使用 if-else语句来进行判断,而 Optional 类的出现是为了简化对 null的判断。

什么是 Optional 类

java.util.Optional<T>类是一个封装了Optional值的容器对象。如果值存在,调用get()方法可以获取值,并且调用isPresent()方法会返回true;如果值不存在,那么调用isPresent()方法会返回 false,并且调用 get()方法会抛出异常。

如何创建 Optional 对象

Optional类提供类三个方法用于实例化一个Optional对象,它们分别为empty()of()ofNullable(),这三个方法都是静态方法,可以直接调用。


  • empty()方法用于创建一个没有值的Optional对象:
1
Optional<String> emptyOpt = Optional.empty();

empty()方法创建的对象没有值,如果对emptyOpt变量调用isPresent()方法会返回false,调用get()方法抛出NullPointerException异常。


  • of()方法使用一个非空的值创建Optional对象:
1
2
String str = "Hello World";
Optional<String> notNullOpt = Optional.of(str);

  • ofNullable()方法接收一个可以为null的值:
1
Optional<String> nullableOpt = Optional.ofNullable(str);

如果str的值为null,得到的nullableOpt是一个没有值的Optional对象。

提取 Optional 对象中的值

orElse(var):如果有值就返回,否则返回var作为默认值;

orElseGet():与orElse()方法作用类似,区别在于生成默认值的方式不同。该方法接受一个Supplier<? extends T>函数式接口参数,用于生成默认值;

orElseThrow():与前面介绍的get()方法类似,当值为null时调用这两个方法都会抛出NullPointerException异常,区别在于该方法可以指定抛出的异常类型。

具体用法

1
2
3
4
5
String str = "Hello World";
Optional<String> strOpt = Optional.of(str);
String orElseResult = strOpt.orElse("Hello Shanghai");
String orElseGet = strOpt.orElseGet(() -> "Hello Shanghai");
String orElseThrow = strOpt.orElseThrow(() -> new IllegalArgumentException("Argument 'str' cannot be null or blank."));

如何正确使用 Optional 类

  1. 尽量避免在程序中直接调用Optional对象的get()isPresent()方法;

直接调用get()方法是很危险的做法,如果Optional的值为空,那么毫无疑问会抛出NullPointerException异常,而为了调用get()方法而使用isPresent()方法作为空值检查,这种做法与传统的用if语句块做空值检查没有任何区别。

  1. 避免使用Optional类型声明实体类的属性;

这个类在设计的时候就没有考虑过用来作为类的属性,可以查看Optional的源代码,你会发现它没有实现java.io.Serializable接口,也就是说如果你用到一些orm框架的二级缓存,使用Optional作为实体类的属性没法被序列化。

  1. 当你很确定一个对象不可能为null的时候,应该使用of()方法,否则,尽可能使用ofNullable()方法创建 Optional 对象。

使用示例

  1. 简化嵌套 if-else
1
2
3
4
5
6
7
8
9
10
11
User user = ...
if (user != null) {
String userName = user.getUserName();
if (userName != null) {
return userName.toUpperCase();
} else {
return null;
}
} else {
return null;
}

上面的代码可以简化成:

1
2
3
4
5
6
User user = ...
Optional<User> userOpt = Optional.ofNullable(user);

return userOpt.map(User::getUserName)
.map(String::toUpperCase)
.orElse(null);
  1. 判重

如判断用户名不能重复的逻辑,根据用户名从数据库中查询一个用户,如果不为null就抛出异常告诉前端用户已存在:

1
2
3
4
User existUser = userDAO.findById(user.getUsername());
if (existUser != null) {
throw new AppException("用户名已存在");
}

可以简写为:

1
2
3
4
5
User user = userDAO.findById(user.getId());
// ifPresent的方法体只有在 Optional 值不为空的时候才会执行
Optional.ofNullable(user).ifPresent(it -> {
throw new AppException("用户名已存在");
})

Java8 Optional 类的使用
http://example.com/2025/03/18/Java8 Optional 类的使用/
作者
Moonike
发布于
2025年3月18日
更新于
2025年5月20日
许可协议