java.util.Optional

简介

为了避免null导致NullPointerException,JAVA8新增了Optional来避免这种情况的发生。

当变量T存在时, Optional类只是对类简单封装。当变量T不存在时,缺失的值会被建模成一个“空”的Optional对象,由方法Optional.empty()返回。

 null引用和Optional.empty()有什么本质的区别吗?从语义上,可以把它们当作一回事儿,但是实际中它们之间的差别非常大:如果尝试引用一个null, 一定会触发NullPointerException,而Optional.empty()则没这个问题,它是Optional类的一个有效对象,多种场景都能正常调用。

但如果你就是不使用Optional,那么可以理解为你是允许该对象为null。

String name;按照JAVA8约定,这种形式的变量是不允许出现null情况的,如果出现null,则只能说是业务流程出现问题。

Optional<String> name;按照JAVA8约定,这种形式的变量是允许出现null情况的。

方法使用案例

Optional<Car> optCar = Optional.empty();声明一个空的Optional

Optional<Car> optCar = Optional.of(car);依据一个非空值创建Optional

Optional<Car> optCar = Optional.ofNullable(car);可接受null的Optional

Optional<Insurance> optInsurance = Optional.ofNullable(insurance);

Optional<String> name = optInsurance.map(Insurance::getName);可以把Optional对象看成一种特殊的集合数据,它至多包含一个元素。如果Optional包含一个值,那函数就将该值作为参数传递给map,对该值进行转换。如果Optional为空,就什么也不做。使用 map 来从Optional对象中提取和转换值

person.flatMap(Person::getCar).flatMap(Car::getInsurance).map(Insurance::getName).orElse("Unknown");flatMap方法接受一个函数作为参数,这个函数的返回值是另一个流。这个方法会应用到流中的每一个元素,最终形成一个新的流的流。但是flagMap会用流的内容替换每个新生成的流。换句话说,由方法生成的各个流会被合并或者扁平化为一个单一的流。

optInsurance.filter(insurance->"CambridgeInsurance".equals(insurance.getName())).ifPresent(x->System.out.println("ok"));filter方法接受一个谓词作为参数。 如果Optional对象的值存在,并且它符合谓词的条件,filter方法就返回其值;否则它就返回一个空的Optional对象。如果你还记得我们可以将Optional看成最多包含一个元素的Stream对象,这个方法的行为就非常清晰了。 如果Optional对象为空,它不做任何操作,反之,它就对Optional对象中包含的值施加谓词操作。如果该操作的结果为true,它不做任何改变,直接返回该Optional对象,否则就将该值过滤掉,将Optional的值置空。

常用方法API

①get()是这些方法中最简单但又最不安全的方法。如果变量存在,它直接返回封装的变量

值,否则就抛出一个NoSuchElementException异常。所以,除非你非常确定Optional变量一定包含值,否则使用这个方法是个相当糟糕的主意。此外,这种方式即便相对于嵌套式的null检查,也并未体现出多大的改进。

②orElse(T other)允许在Optional对象不包含值时提供一个默认值。

③orElseGet(Supplier<? extends T> other)是orElse方法的延迟调用版, Supplier

方法只有在Optional对象不含值时才执行调用。如果创建默认值是件耗时费力的工作,

应考虑采用这种方式,或者需要非常确定某个方法仅在Optional为空时才进行调用,也可以考虑该方式。

④orElseThrow(Supplier<? extends X> exceptionSupplier)和get方法非常类似,它们遭遇Optional对象为空时都会抛出一个异常,但是使用orElseThrow可以定制希望抛出的异常类型。

⑤ifPresent(Consumer<? super T>)能在变量值存在时执行一个作为参数传入的方法,否则就不进行任何操作。

API列表

1.empty:返回一个空的Optional实例。

2.filter:如果值存在并且满足提供的谓词,就返回包含该值的 Optional对象;否则返回一个空的Optional对象。

3.flatMap:如果值存在,就对该值执行提供的mapping函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象。

4.get:如果该值存在,将该值用Optional封装返回,否则抛出一个NoSuchElementException异常。

5.ifPresent:如果值存在,就执行使用该值的方法调用,否则什么也不做。

6.isPresent:如果值存在就返回true,否则返回false。

7.map:如果值存在,就对该值执行提供的mapping函数调用。

8.of:将指定值用Optional封装之后返回,如果该值为null,则抛出一个NullPointerException异常。

9.ofNullable:将指定值用Optional封装之后返回,如果该值为null,则返回一个空的Optional对象。

10.orElse:如果有值则将其返回,否则返回一个默认值。

11.orElseGet:如果有值则将其返回,否则返回一个由指定的 Supplier接口生成的值。

12.orElseThrow:如果有值则将其返回,否则抛出一个由指定的 Supplier接口生成的异常。

改造老旧代码

Null转Optional:

Optional<Object> value =

Optional.ofNullable(map.get("key"));

处理异常:

try {

return Optional.of(Integer.parseInt(s));

} catch (NumberFormatException e) {

return Optional.empty();

}

注意事项

①Optional也提供了类似的基础类型:OptionalInt、 OptionalLong以及OptionalDouble。但是这些基础类型却不支持map、flatMap以及filter方法。

②Optional对象无法由基础类型的Optional组合构成,比如:OptionalInt类型的对象,你就不能将其作为方法引用传递给另一个Optional对象的flatMap方法。

③Optional类并未实现Serializable接口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章