Optional 类
作用
首次出现在 Google 的 Guava 类库中,在 Java 8 中引入,用于解决 NullPointerException 问题,避免代码中频繁的 null 检查。
数据结构
Optional 类是对原有数据类型的一个封装。如果原有变量不存在,Optional 类会通过 Optional.empty() 方法返回空的 Optional 对象,避免返回 null 值。
使用
创建
创建空 Optional:
Optional<Car> option = Optional.empty();创建非空 Optional:
Optional<Car> option = Optional.of(myCar);创建可以包含 null 值的 Optional:
Optional<Car> option = Optional.ofNullable(yourCar);判断值/获取值
判断是否存在值 isPresent(),获取原数据 get() :
if(option.isPresent()) {
System.out.println(option.get());
}ifPresent 会接收一个消费者类型函数式接口的实现,如果 Optional 实例中的值不为空,则调用 Cosumer 的 accept 方法对 value 进行消费,若值为空则不做处理:
public void ifPresent(Consumer<? super T> action) {
if(value != null) {
action.accept(value);
}
}使用 ifPresent 来代替 isPresent() 与 get() 方法:
optional.isPresent((val) -> System.out.println(val));orElse() : 同 get() 方法,在值为空时返回默认值
Optional<Car> option = Optional.empty();
System.out.println(option.orElse("MINI COOPER");orElseGet() :接收一个 Supplier 类型的 函数式接口 实现,功能同 orElse ()
String Optional.empty().orElseGet(() -> "Default");orElseThrow() :接收 函数式接口, 如无值抛出异常
map :使用 Lambda 表达式对 Optional 对象进行操作,map 函数返回前会封装为 Optional 对象。
使用 Stream 的 map:
public Optional<Employee> findEmployeeById(int id) {
// do something
}
public List<Employee> findEmplogyeeByIds(List<Integer> ids) {
return ids.stream()
.map(this::findEmployeeById)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}使用 Optional 的 map:
public List<Employee> findEmplogyeeByIds(List<Integer> ids) {
return ids.stream()
.map(this::findEmployeeById)
.flatMap(optional -> optional.map(Stream::of)
.orElseGet(Stream::empty))
.collect(Collector.toList());
}flatMap :与 map 类似,区别在与 flatMap 的返回值必须是 Optional,不会像 map 那样进行封装。
filter : 对 Optional 对象进行校验,如果满足条件返回原对象,如果不满足返回空 Optional 对象。
Optional<String> longName = username.filter((value) -> value.length() > 2);
System.out.println(longName.orElse("The name is less than 2 characters"));获取 optional 对象的属性值
Optional<Person> person = getPerson(index);
return person.map(Person::getName).orElse("unknown");场景
使用 Optional 的目的是为了上开发者不要忘记非空检查。
Optional 类的缺点有:
- 不能避免 NPE 问题,只是将异常转化为
NoSuchElementException - 更难理解
- 效率较低
阿里《Java开发手册》建议对于级联调用 obj.getA().getB().getC() 使用 Optional 类来防止 NPE 问题。如果在不使用链式语法的场景,使用 null 来判断效率更高。
尽量避免将 Optional 用于类属性,方法参数与集合元素中,因为完全可以使用 null, 违反了使用 Optional 类的初衷。