一、简介

Optional 是一个容器对象,可以包含也可以不包含非 NULL 值。Optional 在 Java 8 中引入,目的是解决NullPointerException(NPE)的问题。本质上,Optional 是一个包装器类,其中包含对其他对象的引用。在这种情况下,对象只是指向内存位置的指针,并且也可以指向任何内容。从其它角度看,Optional 提供一种类型级解决方案来表示可选值而不是空引用。

1. 在 Optional 之前

在 Java 8 之前,程序员将返回Null而不是 Optional。这种方法有一些缺点。一种是没有明确的方法来表示NULL可能是一个特殊值。相比之下,在 API 中返回 Optional 是明确的声明,其中可能没有值。如果我们要确保不会出现空指针异常,则需要对每个引用进行显式的空检查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void getIsoCode(User user){
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
}

2. 在 Optional 之后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class OptionalDemo {
public static void main(String[] args) {
Optional<Member> optional = getMemberByIdFromDB();
optional.ifPresent(mem -> {
System.out.println("会员姓名是:" + mem.getName());
});
}

public static Optional<Member> getMemberByIdFromDB() {
boolean hasName = true;
if (hasName) {
return Optional.of(new Member("张三"));
}
return Optional.empty();
}
}

getMemberByIdFromDB()方法返回了Optional<Member>作为结果,这样就表明Member可能存在,也可能不存在,这时候就可以在 Optional 的ifPresent()方法中使用Lambda表达式来直接打印结果。

Optional 之所以可以解决NullPointerException(NPE)的问题,是因为它明确的告诉我们,不需要对它进行判空。它就好像十字路口的路标,明确地告诉你该往哪走。


二、使用

1. 创建

empty()

可以使用静态方法empty()创建一个空的 Optional 对象

1
2
Optional<String> empty = Optional.empty();
System.out.println(empty); // 输出:Optional.empty

of()

可以使用静态方法of()创建一个非空的 Optional 对象

1
2
Optional<String> opt = Optional.of("张三");
System.out.println(opt); // 输出:Optional[张三]

当然了,传递给of()方法的参数必须是非空的,也就是说不能为NULL,否则仍然会抛出NullPointerException

ofNullable()

可以使用静态方法ofNullable()创建一个即可空又可非空的 Optional 对象

1
2
3
String name = null;
Optional<String> optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull); // 输出:Optional.empty

ofNullable()方法内部有一个三元表达式,如果为参数为NULL,则返回私有常量EMPTY;否则使用new关键字创建了一个新的 Optional 对象——不会再抛出NullPointerException(NPE)异常了。

2. 判断值是否存在

可以通过方法isPresent()判断一个 Optional 对象是否存在,如果存在,该方法返回true,否则返回false——取代了obj != null的判断。

1
2
3
4
5
Optional<String> opt = Optional.of("张三");
System.out.println(opt.isPresent()); // 输出:true

Optional<String> optOrNull = Optional.ofNullable(null);
System.out.println(opt.isPresent()); // 输出:false

3. 非空表达式

Optional 类有一个非常现代化的方法——ifPresent(),允许我们使用函数式编程的方式执行一些代码,因此,我把它称为非空表达式。可以直接将 Lambda 表达式传递给该方法,代码更加简洁,更加直观。

1
2
Optional<String> opt = Optional.of("张三");
opt.ifPresent(str -> System.out.println(str.length()));

4. 设置(获取)默认值


相关引用:

  1. 掘进稀土 - Java8 Optional用法和最佳实践
  2. CSDN - 干货,一文彻底搞懂 Java 的 Optional