专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java新特性:Optional类(java的option类)

temp10 2025-07-03 19:19:31 java教程 4 ℃ 0 评论

1、Optional类概述

1.1、Optional类介绍

Optional类是Java 8 才引入的,Optional 是个容器,它可以保存类型 T 的值,或者仅仅保存 null。Optional 提供了很多方法,这样我们就不用显式进行空值检测。Optional 类的引入很好的解决空指针异常。

Java 8 引入 Optional 类,用来解决 NullPointerException。 Optional 代替 if…else 解决空指针问题,使代码更加简洁。

Java新特性:Optional类(java的option类)

1.2、Java8之前的空指针异常判断

Java 在使用对象过程中,访问任何方法或属性都可能导致 NullPointerException:

例如我们通过以下方法,获取存在 student 对象中的 Age 值。

在这样的示例中,如果我们想要避免由 studentstudent.age 为空而导致的空指针问题,我们就需要采用防御式检查减少 NullPointerException(在访问每一个值之前对其进行明确地检查):

然而,这种方案并不是很理想,因为为此会多出多个不同的退出点(return),使得代码维护变得艰难,之后每个可能的 null 检查都会新增一个退出点。

为了简化这个过程,我们来看看用 Optional 类是怎么做的。

1.3、Java8之后Optional的使用

当需要判断的量多时,此时的这些判断语句可能会导致代码臃肿冗余,为此 Java8 特意推出了 Optional 类来帮助我们去处理空指针异常。

下面是 Optional 的一些基本用法:

2、Optional类使用

2.1、Optional类常用方法总结

2.2、Optional对象创建

2.2.1、Optional.empty()方法

使用 Optional.empty() 方法声明一个空的 Optional:

2.2.2、Optional.of(T t)方法

使用 Optional.of(T t) 方法创建一个包含非空值的 Optional 对象 (不推荐):

如果 student 为 null,这段代码会立即抛出一个 NullPointerException,而不是等到访问 student 的属性值时才返回一个错误。

2.2.3、Optional.ofNullable(T t)方法

使用 Optional.ofNullable(T t) 方法创建一个包含可能为空的值的 Optional 对象 (推荐):

2.3、Optional对象获取

2.3.1、get()方法

get() 方法,如果变量存在,它直接返回封装的变量值,否则就抛出一个 NoSuchElementException 异常,不推荐使用:

optional.map(Student::getAge).get()

2.3.2、orElse(T other)方法

orElse(T other) 方法,它允许你在 Optional 对象不包含值时提供一个默认值:

optional.map(Student::getAge).orElse(20));

2.3.3、orElseGet(Supplier<? extends T> other)方法

orElseGet(Supplier<? extends T> other) 方法,它是 orElse 方法的延迟调用版,Supplier 方法只有在 Optional 对象不含值时才执行调用(懒加载):

optional.map(Student::getAge).orElseGet(() -> Integer.MAX_VALUE);

2.3.4、orElseThrow(Supplier<? extends X> exceptionSupplier)方法

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

optional.orElseThrow(() -> new RuntimeException("student不存在!"));

2.3.5、ifPresent(Consumer<? super T> consumer)方法

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

optional.ifPresent(o -> o.setAge(18));

2.4、Optional对象中值的提取和转换

2.4.1、map()方法

map() 方法,如果值存在,就对该值执行提供的 mapping 函数调用,如果值不存在,则返回一个空的 Optional 对象。

引入 Optional 以前:

引入 Optional 以后:

Optional 的 map 方法和 Java 8 中 Stream 的 map 方法相差无几。

2.4.2、flatMap()方法

flatMap() 方法,对于嵌套式的 Optional 结构,我们应该使用 flatMap 方法,将两层的 Optional 合并成一个。

我们试着重构以下代码:

由于我们刚刚学习了如何使用 map,我们的第一反应可能是我们可以利用 map 重写之前的代码:

不幸的是,这段代码无法通过编译。为什么呢? optPerson 是 Optional<Person> 类型的 变量, 调用 map 方法应该没有问题。但 getCar 返回的是一个 Optional<Car> 类型的对象,这意味着 map 操作的结果是一个 Optional<Optional<Car>> 类型的对象。因此,它对 getInsurance 的调用是非法的。

下面应用 map 和 flatMap 对上述示例进行重写:

2.5、Optional对象其他方法

2.5.1、isPresent()方法

可以使用 isPresent() 方法检查 Optional 对象是否包含非空值,例如:

2.5.2、filter()方法

filter() 方法接受一个谓词作为参数。如果 Optional 对象的值存在,并且它符合谓词的条件,filter 方法就返回其值,否则它就返回一个空的 Optional 对象。

比如,你可能需要检查保险公司的名称是否为 “Cambridge-Insurance”。

使用 Optional 对象的 filter 方法,这段代码可以重构如下:

3、Optional注意事项

3.1、Optional的序列化问题

由于 Optiona l类设计时就没特别考虑将其作为类的字段使用,所以它也并未实现 Serializable 接口。由于这个原因,如果你的应用使用了某些要求序列化的库或者框架,在域模型中使用Optional,有可能引发应用程序故障。

然而,我们相信,通过前面的介绍,我们已经看到用 Optional 声明域模型中的某些类型是个不错的主意,尤其是你需要遍历有可能全部或部分为空,或者可能不存在的对象时。如果你一定要实现序列化的域模型,作为替代方案, 我们建议你像下面这个例子那样,提供一个能访问声明为 Optional、变量值可能缺失的接口,代码清单如下:

3.2、避免使用基础类型的 Optional 对象

Optional 提供了的一些基础类型 —— OptionalInt、OptionalLong 以及 OptionalDouble ,但不推荐大家使用基础类型的 Optional,因为基础类型的 Optional 不支持 map、 flatMap 以及 filter 方法,而这些却是 Optional 类常用的方法。可以使用 Optional<Int>, Optional<Long>, Optional<Double> 等替代。3. orElse方法的使用

3.3、orElse方法的使用

orElse 中调用的方法一直都会被执行,orElseGet 方法只有在 Optional 对象不含值时才会被调用,所以使用 orElse 方法时需要谨慎, 以免误执行某些不被预期的操作。此种情况下,可使用 orElseGet 方法代替它。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表