Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 类是个容器,它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常(NullPointerException)。
Optional 类位于java.util.Optional包下,类似Optional的还有OptionalDouble、OptionalInt、OptionalLong
Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。
一、类签名
/**
* 可能包含也可能不包含非空值的容器对象。 如果存在值,isPresent()将返回true ,get()将返回该值。
*
* 提供了依赖于包含值的存在与否的其他方法,例如orElse() (如果值不存在则返回默认值和ifPresent() (如果值存在则执行代码块)。
*
* 这是一个基于值的类;在Optional实例上使用身份敏感操作(包括引用相等性 ( == )、身份哈希码或同步)可能会产生不可预测的结果,应该避免。
*
* @since 1.8
*/
public final class Optional<T> extends Object{};
二、类中的方法
1、静态方法
| 方法定义 | 描述 |
|---|---|
public static<T> Optional<T> empty() | 返回一个空的Optional实例。 此可选项不存在值。 |
public static <T> Optional<T> of(T value) | 返回具有 Optional的当前非空值的Optional。 |
public static <T> Optional<T> ofNullable(T value) | 返回一个 Optional指定值的Optional,如果非空,则返回一个空的 Optional 。 |
2、具体方法
| 方法定义 | 描述 |
|---|---|
public T get() | 如果 Optional中存在值,则返回值,否则抛出 NoSuchElementException 。 |
public boolean isPresent() | 如果存在值,则返回 true ,否则为 false 。 |
public void ifPresent(Consumer<? super T> consumer) | 如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。 |
public Optional<T> filter(Predicate<? super T> predicate) | 如果一个值存在,并且该值给定的谓词相匹配时,返回一个 Optional描述的值,否则返回一个空的 Optional 。 |
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) | 如果存在值,则应用提供的映射函数,如果结果不为空,则返回一个Optional结果的Optional 。 否则返回一个空的Optional 。 |
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) | 如果一个值存在,应用提供的Optional映射函数给它,返回该结果,否则返回一个空的Optional 。 这种方法类似于map(Function) ,但是提供的映射器是一个结果已经是Optional映射器,如果被调用, flatMap不会用额外的Optional 。 |
public T orElse(T other) | 返回值如果存在,否则返回 other 。 |
public T orElseGet(Supplier<? extends T> other) | 返回值(如果存在),否则调用 other并返回该调用的结果。 |
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X | 返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。 |
public boolean equals(Object obj) | 指示某个其他对象是否等于此可选项 |
public int hashCode() | 返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。 |
public String toString() | 返回此可选的非空字符串表示,适用于调试。 准确的表示格式是未指定的,可能会在实现和版本之间变化。 |
四、JDK8以前解决空指针
在jdk8以前我们为了避免空指针,我们一般是对每一个操作的对象进行非空判断,,否则就会让你体验一下非定时炸弹NullPointerException异常
main方法
/**
* 创建 Optional 实例
*
* @author Minhat
*/
public class OptionalTest {
public static void main(String[] args) {
jdk8BeforeUsage();
}
/**
* 在 Java 8 之前,任何访问对象方法或属性的调用都可能导致NullPointerException
*/
public static void jdk8BeforeUsage() {
User1 user1 = null;
if (user != null) {
String username = user.getUsername();
if (username != null) {
System.out.println("用户名为:" + username);
}
}
}
}
用户类
/**
* 用户类
*
* @author Minhat
*/
@Data
public class User1 {
/**
* 用户名
*/
private String username;
}
以上代码为了解决空指针异常,对每一个对象都进行了非空判断,如果对象引用层数少看似没什么影响,但是如果一个对象A引用对象B引用对象C,那么我们获取C对象时就要写V字大法的判断了:
if(a != null) {
if(b != null) {
if(c != null) {
if(d != null) {
if(d != null) {
if(e != null) {
if(f != null) {
...
// 只要你够任性的挑剔对象,那么你总有一天会找到属于你的真爱对象
}
}
}
}
}
}
}
当你看到这样的代码是不是,大写一个我艹,太难维护了;为了简化这个过程我们来看看用 Optional 类是怎么做的。从创建和验证实例,到使用其不同的方法,并与其它返回相同类型的方法相结合,下面是吸收一下 Optional 骚操作。
五、创建Optional实例
如何创建一个Optional实例呢?下面我们来看一下Optional的构造方法源码:
/**
* 构造一个空实例。
*
* @implNote 通常,每个VM应该只存在一个空实例EMPTY 。
*/
private Optional() {
this.value = null;
}
/**
*构造一个具有当前值的实例。
*
* @param value 要存在的非空值
* @throws NullPointerException 如果值为null
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
对你没看错,构造方法都被私有化了,貌似看来你永远也得不到Optional这个对象,但是请转移你的目光,既然不能直接直接得创建实例,那么我们再来看看有没有其他方式呢,下面我们来一探究竟。
1、Optional.empty()
Optional.empty()的对象可以包含值,也可以值为空,你可以是用静态方法empty()创建一个空的Optional对象。
(1)、构造方法签名
/**
* 返回一个空的Optional实例。 此可选项不存在值。
*
* @apiNote 尽管这样做可能很诱人,但避免通过将==与Option.empty()返回的实例进行比较来测试对象是否为空。
* 不能保证它是单例。 相反,使用isPresent() 。
*
* @param <T> 不存在值的类型
* @return 一个空的 Optional
*/
public static<T> Optional<T> empty();
(2)、示例代码
/**
* 使用Optional.empty()创建一个空值为空的Optional对象
*/
public static void useEmptyCreateOptional() {
Optional<Object> empty = Optional.empty();
// 使用Optional的isPresent()方法判断Optional的值是否为空
System.out.println("Optional的值是否为空:" + empty.isPresent());
}
(3)、运行结果
Optional的值是否为空:false
Process finished with exit code 0
从运行结果可以看出Optional的值为空。
2、Optional.of(T value)
Optional.of(T value)返回具有 Optional的当前非空值的Optional。传入的value的值不能为null,如果value的值为空则抛出NullPointerException异常。
(1)、构造方法签名
/**
* 返回具有Optional的当前非空值的Optional。
*
* @param 要存在的值,它必须是非空值
* @throws NullPointerException 如果值为空抛出
*/
public static <T> Optional<T> of(T value);
(2)、示例代码
/**
* 使用Optional.of()创建Optional对象
*/
public static void useOfCreateOptional() {
// 创建一个非空的Optional对象,不会抛出空指针异常
Optional<String> notNullOpt = Optional.of("小红帽");
System.out.println("Optional的值是否为空:" + notNullOpt.isPresent());
// 创建一个空的Optional对象,会抛出空指针异常
Optional<String> isNullOpt = Optional.of(null);
System.out.println("Optional的值是否为空:" + isNullOpt.isPresent());
}
(3)、运行结果
Optional的值是否为空:true
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at cn.minhat.other.OptionalTest.userOfCreateOptional(OptionalTest.java:48)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:14)
Process finished with exit code 1
从运行结果中可以看出如果Optional.of(T),传入的参数不为空不会抛出空指针异常,如果传入的值为null则抛出空指针异常。因此在是用Optional.of()`方法是要确保传入的对象不能为空否则就会抛出空指针异常。
3、Optional.ofNullable(T value)
Optional.ofNullable(T value)返回一个 Optional指定值的Optional,如果非空,则返回一个空的 Optional 。使用该方法即使value为空也不会发生任何异常。
(1)、构造方法签名
/**
* 返回一个 Optional指定值的Optional,如果非空,则返回一个空的 Optional 。
*
* @param <T> 该类的值
* @param value 可能为null的值来描述
* @return 一个Optional,如果指定的值不为空,则为当前值,否则为空 Optional
*/
public static <T> Optional<T> ofNullable(T value);
(2)、示例代码
/**
* 使用Optional.ofNullable()创建Optional对象
*/
public static void useOfNullableCreateOptional() {
// 创建一个非空的Optional对象,不会抛出空指针异常
Optional<String> notNullOpt = Optional.ofNullable("小红帽");
System.out.println("Optional的值是否为空:" + notNullOpt.isPresent());
// 创建一个空的Optional对象,会抛出空指针异常
Optional<String> isNullOpt = Optional.ofNullable(null);
System.out.println("Optional的值是否为空:" + isNullOpt.isPresent());
}
(3)、运行结果
Optional的值是否为空:true
Optional的值是否为空:false
Process finished with exit code 0
从运行结果中可以看出使用Optional.ofNullable(T)创建Optional的对象,不管传入的值是否为null都不会报错。因此在使用Optional.ofNullable(T)方法是通常处理我们不确定传入的参数是否为空的值。
六、Optional的具体方法
1、get()
get()如果此Optional存在值,则返回该值,否则抛出NoSuchElementException 。
(1)、方法签名
/**
* 如果Optional中存在值,则返回值,否则抛出 NoSuchElementException 。
*
* @return 该Optional非空值
* @throws NoSuchElementException 如果没有值存在
*
* @see Optional#isPresent()
*/
public T get();
(2)、示例代码
/**
* 使用Optional的get()方法。
* 如果 Optional中存在值,则返回值,否则抛出NoSuchElementException 。
*/
public static void useGetMethod() {
// 创建一个非空的Optional对象
Optional<String> notNullOpt = Optional.of("小红帽");
System.out.println("Optional中的值:" + notNullOpt.get());
// 创建一个空的Optional对象
Optional<String> isNullOpt = Optional.empty();
System.out.println("Optional中的值:" + isNullOpt.get());
}
(3)、运行结果
Optional中的值:小红帽
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at cn.minhat.other.OptionalTest.useGetMethod(OptionalTest.java:78)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:16)
Process finished with exit code 1
可以看出我们使用get()方法获取Optional的值如果Optional中存在值,则返回值,否则抛出 NoSuchElementException 。
2、isPresent()判断只是否存在
isPresent()如果存在值,则返回 true ,否则为 false 。
(1)、方法签名
/**
* 如果存在值,则返回true,否则为false 。
*
* @return true若有存在值,否则为false
*/
public boolean isPresent();
(2)、示例代码
/**
* 使用Optional的isPresent()方法。
* 如果存在值,则返回 `true` ,否则为 `false` 。
*/
public static void useIsPresentMethod() {
// 创建一个非空的Optional对象
Optional<String> notNullOpt = Optional.of("小红帽");
System.out.println("Optional中是否有值:" + notNullOpt.isPresent());
// 创建一个空的Optional对象
Optional<String> isNullOpt = Optional.empty();
System.out.println("Optional中是否有值:" + isNullOpt.isPresent());
}
(3)、运行结果
Optional中是否有值:true
Optional中是否有值:false
Process finished with exit code 0
3、ifPresent(Consumer<? super T> consumer)
ifPresent(Consumer<? super T> consumer)如果存在值,则使用该值就调用Consume函数式接口,否则不执行任何操作。如果值存在且consumer为空则抛出NullPointerException异常。
(1)、方法签名
/**
* 如果存在值,则使用该值调用指定的Consumer,否则不执行任何操作。
*
* @param consumer 如果存在值,则执行Consumer
* @throws NullPointerException 如果值不为Null,consumer为空
*/
public void ifPresent(Consumer<? super T> consumer);
(2)、示例代码
/**
* 使用Optional的ifPresent()方法。
* 如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。
* 如果值存在且Consumer为空则抛出NullPointerException异常。
*/
public static void useIfPresent() {
// 创建一个非空的Optional对象
Optional<String> notNullOpt = Optional.of("小红帽");
notNullOpt.ifPresent(s -> System.out.println("调用了Consumer接口"));
// 创建一个空的Optional对象
Optional<String> isNullOpt = Optional.empty();
isNullOpt.ifPresent(s -> System.out.println("调用了Consumer接口"));
// 使用值非空的Optional调用ifPresent,传入null的Consumer
notNullOpt.ifPresent(null);
}
(3)、运行结果
调用了Consumer接口
Exception in thread "main" java.lang.NullPointerException
at java.util.Optional.ifPresent(Optional.java:159)
at cn.minhat.other.OptionalTest.useIfPresent(OptionalTest.java:112)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:18)
Process finished with exit code 1
从运行结果可以看出:
- Optional的值不为空并且Consumer不为空,ifPresent方法不会发生任何异常并且调用Consumer函数式接口
- Optional的值为空但是Consumer不为空,ifPresent方法不会发生任何异常但是不调用Consumer函数式接口
- Optional的值不为空但是Consumer为空,ifPresent会直接抛出
NullPointerException异常
4、filter(Predicate<? super T> predicate)
此方法的作用是单签的Optional实例不为空,则执行函数式接口Predicate,如果满足条件则返回当前的Optional实例否则返回一个空的Optional实例。
filter(Predicate<? super T> predicate)有以下特性:
- 如果Optional的值不为空,并且Predicate函数式接口返回为true则返回当前的Optional
- 如果Optional的值不为空,并且Predicate函数式接口返回为true则返回一个空Optional
- 如果Optional的值为空则返回当前的Optional
- 如果函数式接口
Predicate为空则直接抛出NullPointerException异常
(1)、方法签名
/**
* 如果一个值存在,并且该值给定的谓词相匹配时,返回一个 Optional描述的值,否则返回一个空的 Optional 。
*
* @param 一个应用于该值的Predicate(如果存在)
* @return 一个 Optional描述此的值 Optional一个值是否存在,并且值给定的Predicate相匹配,否则一个空 Optional
* @throws NullPointerException 如果Predicate为空
*/
public Optional<T> filter(Predicate<? super T> predicate);
(2)、示例代码
/**
* 使用Optional的filter()方法。
* 如果函数式接口Predicate为空则直接抛出NullPointerException异常
* 如果Optional的值不为空,并且Predicate函数式接口返回为true则返回当前的Optional
* 如果Optional的值不为空,并且Predicate函数式接口返回为true则返回一个空Optional
* 如果Optional的值为空则返回当前的Optional
*/
public static void useFilter() {
// 创建一个非空的Optional对象
Optional<String> notNullOpt = Optional.of("小红帽");
// Predicate返回true
System.out.println("Optional中是否有值:" + notNullOpt.filter(s -> true).isPresent());
// Predicate返回false
System.out.println("Optional中是否有值:" + notNullOpt.filter(s -> false).isPresent());
// 创建一个空的Optional对象
Optional<String> isNullOpt = Optional.empty();
// Predicate返回true
System.out.println("Optional中是否有值:" + isNullOpt.filter(s -> true).isPresent());
// 传入Null的Predicate
System.out.println("Optional中是否有值:" + notNullOpt.filter(null).isPresent());
}
(3)、运行结果
Optional中是否有值:true
Optional中是否有值:false
Optional中是否有值:false
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.filter(Optional.java:174)
at cn.minhat.other.OptionalTest.useFilter(OptionalTest.java:137)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:19)
Process finished with exit code 1
5、map(Function<? super T, ? extends U> mapper)
如果存在值,则对其应用提供的Function函数接口,如果结果非空,则返回描述结果的Optional 。 否则返回一个空的Optional 。
(1)、方法签名
/**
* 如果存在值,则应用提供的映射函数,如果结果不为空,则返回一个Optional结果的Optional 。 否则返回一个空的Optional 。
*
* @apiNote 此方法支持对可选值进行后处理,无需明确检查返回状态。 例如,以下代码遍历文件名流,选择尚未处理的代码,
* 然后打开该文件,返回Optional<FileInputStream>
*
* <pre>{@code
* Optional<FileInputStream> fis =
* names.stream().filter(name -> !isProcessedYet(name))
* .findFirst()
* .map(name -> new FileInputStream(name));
* }</pre>
*
* 这里, findFirst返回一个Optional<String> ,然后map返回一个Optional<FileInputStream>为所需文件(如果存在)。
*
* @param <U> 映射函数的结果类型
* @param mapper 应用于值的映射函数(如果存在)
* @return 一个 Optional描述了将映射函数应用于该值 Optional的值的 Optional ,如果存在值,否则为空 Optional
* @throws NullPointerException 如果映射函数为空
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper);
(2)、示例代码
/**
* 使用Optional的map()方法。
* 如果传入的Function函数式接口为空则抛出NullPointerException异常。
* 如果Optional的值为null则返回空的Optional。
* 如果Optional的值不为null则调用函数式接口Function,如果函数式接口返回的值为null,则返回空的Optional。
* 如果Optional的值不为null则调用函数式接口Function,如果不为null则返回函数式接口返回的值的Optional实例。
*/
public static void useMap() {
// 如果传入的Function函数式接口为空则抛出NullPointerException异常。
Optional<String> notNullOpt = Optional.of("小红帽");
try {
notNullOpt.map(null);
} catch (NullPointerException e) {
e.printStackTrace();
}
// 如果Optional的值为null则返回空的Optional。
Optional<String> isNullOpt = Optional.empty();
Optional<String> result_1 = isNullOpt.map(s -> "测试:" + s);
System.out.println("Optional中是否有值:" + result_1.isPresent());
// 如果Optional的值不为null则调用函数式接口Function,如果函数式接口返回的值为null。
Optional<Object> result_2 = notNullOpt.map(s -> null);
System.out.println("Optional中是否有值:" + result_2.isPresent());
// 如果Optional的值不为null则调用函数式接口Function,如果不为空则返回函数式接口返回的值的Optional实例。
Optional<Object> result_3 = notNullOpt.map(s -> "测试:" + s);
System.out.println("Optional中是否有值:" + result_3.isPresent() + ",值为:" + result_3.get());
}
(3)、运行结果
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.map(Optional.java:211)
at cn.minhat.other.OptionalTest.useMap(OptionalTest.java:151)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:20)
Optional中是否有值:false
Optional中是否有值:false
Optional中是否有值:true,值为:测试:小红帽
Process finished with exit code 0
5、flatMap(Function<? super T, Optional> mapper)
如果存在一个值,则将提供的Optional承载映射函数应用于它,返回该结果,否则返回一个空的Optional 。 此方法类似于map(Function) ,但提供的映射器的结果已经是Optional ,并且如果调用, flatMap不会用额外的Optional包装它。
(1)、方法签名
/**
* 如果一个值存在,应用提供的Optional映射函数给它,返回该结果,否则返回一个空的Optional 。
* 这种方法类似于map(Function) ,但是提供的映射器是一个结果已经是Optional映射器,
* 如果被调用, flatMap不会用额外的Optional 。
*
* @param <U> 返回的 Optional的类型参数
* @param mapper 应用于值的映射函数,如果存在映射函数
* @return 施加的结果 Optional荷瘤映射函数此的值 Optional ,如果一个值存在,否则一个空 Optional
* @throws NullPointerException 如果映射函数为空或返回空结果
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper);
(2)、示例代码
/**
* 使用Optional的flatMap()方法。
* 如果传入的Function函数式接口为空则抛出NullPointerException异常。
* 如果Optional的值为null则返回空的Optional。
* 如果Optional的值不为null则调用函数式接口Function,如果函数式接口返回的值为null,则抛出NullPointerException异常。
* 如果Optional的值不为null则调用函数式接口Function,并返回Optional实例,如果不为null则返回函数式接口返回的值的Optional实例。
*/
public static void useFlatMap() {
// 如果传入的Function函数式接口为空则抛出NullPointerException异常。
Optional<String> notNullOpt = Optional.of("小红帽");
try {
notNullOpt.flatMap(null);
} catch (NullPointerException e) {
e.printStackTrace();
}
// 如果Optional的值为null则返回空的Optional。
Optional<String> isNullOpt = Optional.empty();
Optional<String> result_1 = isNullOpt.flatMap(s -> Optional.empty() );
System.out.println("Optional中是否有值:" + result_1.isPresent());
// 如果Optional的值不为null则调用函数式接口Function,如果函数式接口返回的值为null,则抛出NullPointerException异常。
try {
Optional<Object> result_2 = notNullOpt.map(s -> null);
System.out.println("Optional中是否有值:" + result_2.isPresent());
} catch (NullPointerException e) {
e.printStackTrace();
}
// 如果Optional的值不为null则调用函数式接口Function,并返回Optional实例,如果不为null则返回函数式接口返回的值的Optional实例。
Optional<Object> result_3 = notNullOpt.flatMap(s -> Optional.of("x想"));
System.out.println("Optional中是否有值:" + result_3.isPresent() + ",值为:" + result_3.get());
}
(3)、运行结果
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.flatMap(Optional.java:237)
at cn.minhat.other.OptionalTest.useFlatMap(OptionalTest.java:183)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:21)
Optional中是否有值:false
Optional中是否有值:false
Optional中是否有值:true,值为:x想
Process finished with exit code 0
6、orElse(T other)
如果Optional的值不为null则返回当前的Optional的值,否则返回other的值。
(1)、方法签名
/**
* 如果存在则返回值,否则返回other。
*
* @param other 如果没有值,则返回值,可能为空
* @return 如果存在,否则 other
*/
public T orElse(T other);
(2)、示例代码
/**
* 如果Optional的值不为null则返回当前的Optional的值,否则返回other的值。
*/
public static void useOrElse() {
// Optional的值不为空
Optional<String> notNullOpt = Optional.of("小红帽");
String result_1 = notNullOpt.orElse("好好学习");
System.out.println("Optional的值为:" + result_1);
// Optional的值不空,返回值不为空
Optional<String> isNullOpt = Optional.empty();
String result_2 = isNullOpt.orElse("好好学习");
System.out.println("Optional的值为:" + result_2);
// Optional的值不空,返回值为空
String result_3 = isNullOpt.orElse(null);
System.out.println("Optional的值为:" + result_3);
}
(3)、运行结果
Optional的值为:小红帽
Optional的值为:好好学习
Optional的值为:null
Process finished with exit code 0
7、orElseGet(Supplier<? extends T> other)
如果Optional的值不为null则返回当前的Optional的值,否则返回Supplier函数式接口的值,如果函数式接口为空则抛出NullPointerException异常。
(1)、方法签名
/**
* 返回值(如果存在),否则调用 other并返回该调用的结果。
*
* @param other 一个 Supplier ,如果没有值,则返回其结果
* @return 值(如果存在)否则other.get()的结果
* @throws NullPointerException 如果值不存在且other为空
*/
public T orElseGet(Supplier<? extends T> other);
(2)、示例代码
/**
* 如果Optional的值不为null则返回当前的Optional的值,否则返回Supplier函数式接口的值,如果函数式接口为空则抛出`NullPointerException`异常。
*/
public static void useOrElseGet() {
// Optional的值不为空,Supplier不为空
Optional<String> notNullOpt = Optional.of("小红帽");
System.out.println("Optional的值为:" + notNullOpt.orElseGet(() -> "小红帽"));
// Optional的值为空,Supplier不为空
Optional<String> isNullOpt = Optional.empty();
System.out.println("Optional的值为:" + isNullOpt.orElseGet(() -> "小红帽"));
// Optional的值为空,Supplier不为空,返回值为空
System.out.println("Optional的值为:" + isNullOpt.orElseGet(() -> null));
// Optional的值为空,Supplier为空
System.out.println("Optional的值为:" + isNullOpt.orElseGet(null));
}
(3)、运行结果
Optional的值为:小红帽
Optional的值为:小红帽
Optional的值为:null
Exception in thread "main" java.lang.NullPointerException
at java.util.Optional.orElseGet(Optional.java:267)
at cn.minhat.other.OptionalTest.useOrElseGet(OptionalTest.java:242)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:24)
Process finished with exit code 1
8、orElseThrow(Supplier<? extends X> exceptionSupplier)
如果Optional的值不为null则返回当前的Optional的值,否则抛出Supplier函数式接口返回的异常,如果函数式接口为空则抛出NullPointerException异常。
(1)、方法签名
/**
* 返回包含的值(如果存在),否则抛出由提供的Supplier创建的异常。
*
* @apiNote 可以使用具有空参数列表的异常构造函数的方法引用作为Supplier。 例如, IllegalStateException::new
*
* @param <X> 要抛出的异常的类型
* @param exceptionSupplier 将返回要抛出的异常的Supplier
* @return Option的值
* @throws X 如果没有值存在
* @throws NullPointerException 如果没有值, exceptionSupplier为空
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X{};
(2)、示例代码
/**
* 如果Optional的值不为null则返回当前的Optional的值,否则抛出Supplier函数式接口返回的异常,如果函数式接口为空则抛出NullPointerException异常。
*/
public static void useOrElseThrow() {
// Optional的值不为空,Supplier不为空
Optional<String> notNullOpt = Optional.of("小红帽");
System.out.println("Optional的值为:" + notNullOpt.orElseThrow(RuntimeException::new));
// Optional的值为空,Supplier不为空
Optional<String> isNullOpt = Optional.empty();
try {
System.out.println("Optional的值为:" + isNullOpt.orElseThrow(RuntimeException::new));
} catch (Exception e) {
e.printStackTrace();
}
// Optional的值为空,Supplier为空
try {
System.out.println("Optional的值为:" + isNullOpt.orElseThrow(null));
} catch (Exception e) {
e.printStackTrace();
}
}
(3)、运行结果
Optional的值为:小红帽
java.lang.RuntimeException
at java.util.Optional.orElseThrow(Optional.java:290)
at cn.minhat.other.OptionalTest.useOrElseThrow(OptionalTest.java:257)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:25)
java.lang.NullPointerException
at java.util.Optional.orElseThrow(Optional.java:290)
at cn.minhat.other.OptionalTest.useOrElseThrow(OptionalTest.java:263)
at cn.minhat.other.OptionalTest.main(OptionalTest.java:25)
Process finished with exit code 0
9、equals(Object obj)
指示其他某个对象是否“等于”此 Optional。 在以下情况下,另一个对象被认为是相等的:
- 同一个Optional
- 两个Optional的值都为null
- 当前值通过Objects.equals()彼此“相等”
(1)、方法源码
/**
* 指示其他某个对象是否“等于”此 Optional。 在以下情况下,另一个对象被认为是相等的:
* <ul>
* <li>同一个Optional
* <li>两个Optional的值都为null
* <li>当前值通过Objects.equals()彼此“相等”
* </ul>
*
* @param 要进行相等测试的对象
* @return 如果另一个对象“等于”这个对象否则 false
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Optional)) {
return false;
}
Optional<?> other = (Optional<?>) obj;
return Objects.equals(value, other.value);
}
(2)、示例代码
/**
* 指示其他某个对象是否“等于”此 Optional。 在以下情况下,另一个对象被认为是相等的:
* - 同一个Optional
* - 两个Optional的值都为null
* - 当前值通过Objects.equals()彼此“相等”
*/
public static void useEquals() {
Optional<String> opt_1 = Optional.of("小红帽");
Optional<String> opt_2 = opt_1;
Optional<String> opt_3 = Optional.of("小红帽");
Optional<String> opt_4 = Optional.empty();
Optional<String> opt_5 = Optional.empty();
System.out.println("opt_1.equals(opt_2):" + opt_1.equals(opt_2));
System.out.println("opt_1.equals(null):" + opt_1.equals(null));
System.out.println("opt_1.equals(Date):" + opt_1.equals(new Date()));
System.out.println("opt_1.equals(opt_3):" + opt_1.equals(opt_3));
System.out.println("opt_4.equals(opt_5):" + opt_4.equals(opt_5));
}
(3)、运行结果
opt_1.equals(opt_2):true
opt_1.equals(null):false
opt_1.equals(Date):false
opt_1.equals(opt_3):true
opt_4.equals(opt_5):true
Process finished with exit code 0
七、总结
Optional 是 Java 语言的有益补充 —— 它旨在减少代码中的 NullPointerExceptions,虽然还不能完全消除这些异常。
它也是精心设计,自然融入 Java 8 函数式支持的功能。
总的来说,这个简单而强大的类有助于创建简单、可读性更强、比对应程序错误更少的程序。