文章目录
- [1. Optional简介](#1. Optional简介)
- [2. 常用的接口](#2. 常用的接口)
-
- [2.1 常用接口简单使用](#2.1 常用接口简单使用)
-
- [2.1.1 创建的常用方法](#2.1.1 创建的常用方法)
- [2.1.2 获取值的常用方法](#2.1.2 获取值的常用方法)
- [2.1.3 判定的常用方法](#2.1.3 判定的常用方法)
- [2.1.4 判定后的操作方法](#2.1.4 判定后的操作方法)
- [2.2 map方法介绍](#2.2 map方法介绍)
- [2.2 其他方法](#2.2 其他方法)
-
- [2.2.1 Filter 方法](#2.2.1 Filter 方法)
- [2.2.2 FlatMap 方法](#2.2.2 FlatMap 方法)
- [3. 常用的实例](#3. 常用的实例)
- [4. 总结](#4. 总结)
1. Optional简介
Optional是在java8中引入的一个新的类,主要解决的问题就是空指针异常(NullPointerException)
原文的翻译(百度翻译,本人英文短板):一个容器对象,它可能包含也可能不包含非null值。如果存在值,isPresent()将返回true。如果没有值,则该对象被认为是空的,isPresent()返回false。
提供了取决于所包含值是否存在的其他方法,如orElse()(如果不存在值,则返回默认值)和ifPresent()(当存在值时执行操作)。
这是一个基于价值的类;程序员应该将相等的实例视为可互换的,不应该使用实例进行同步,否则可能会发生不可预测的行为。例如,在将来的版本中,同步可能会失败。
这里我理解的核心作用就是可以通过 isPresent()
方法来辅助对对象判空,然后通过 map()
, orElse()
,ifPresent()
等方法的结合使用,大大的缩减代码中冗长的if判断。
2. 常用的接口
先介绍一下常用所有的接口;
注意:
1. 此列表是列出了本人觉得有意义的接口不是全部。
2. 当前jdk版本为17,其他版本可能会没有一些方法,例如:`or()` 方法在jdk1.9中增加的
接口名称 | 简要作用描述 |
---|---|
Optional<T> empty() |
构建一个空的Optional 对象 |
Optional<T> of(T value) |
构建一个非空的Optional 对象,如果为空则报错 ! |
Optional<T> ofNullable(T value) |
构建一个Optional 对象,允许为空! |
T get() |
获取一个泛型的对象值,如果值为空,则报错 |
boolean isPresent() |
判空,如果不为null 则为 true |
boolean isEmpty() |
判空,如果为null 则为 true |
ifPresent(Consumer) |
传递一个接口函数对,当数据不为空 的时候执行这个函数 |
ifPresentOrElse(Consumer, Runnable) |
两个参数, 第一个是不为空的时候执行的,第二个是为空的时候执行的。都是接口函数。 |
Optional<T> filter |
对对象的一个过滤 |
Optional<U> map(Function) |
转换方法 |
Optional<U> flatMap(Function) |
转换方法,常用与多层转换一层 |
Optional<T> or(Supplier) |
当得到对象为空 的时候根据接口函数创建一个新的Optional 对象 |
T orElse(T) |
当得到对象为空 的时候获取一个指定泛型对象 |
T orElseThrow() |
不为空 返回对象,为空 则NoSuchElementException |
T orElseThrow(Supplier) |
不为空 返回对象,为空 则指定异常 |
2.1 常用接口简单使用
下面是常用接口的一些简单的演示
2.1.1 创建的常用方法
java
// 1. 构建一个空的 Optional 对象没有任何问题
Optional<Object> empty = Optional.empty();
// 2. 构建一个非空的 Optional 对象没有任何问题
Optional<Object> aa = Optional.of("123");
// 3. 构建一个空的 Optional 对象直接报错 ================ 会报错 of不允许为空
Optional<Object> bb = Optional.of(null);
// 4. 构建一个空的 Optional 对象没有任何问题
Optional<Object> cc = Optional.ofNullable(null);
// 5. 构建一个非空的 Optional 对象没有任何问题
Optional<Object> dd = Optional.ofNullable("123");
2.1.2 获取值的常用方法
java
Optional<Object> cc = Optional.ofNullable(null);
// 1. 如果为空的时候获取值就会直接报错
Object o = cc.get();
// 2. 如果对象为空,则获取 or 中的 get 方法的值,否则则获取cc的 get 方法中的值
Object o1 = cc.or(() -> Optional.ofNullable("123")).get();
// 3. 如果对象为空,则直接获取的是 123, orElse()中的参数是非空的。 如果对象不为空则直接获取到对象的值
Object o2 = cc.orElse("123");
// 4. 如果对象为空,则获取 or 中的 get 方法的值,否则则获取cc的 get 方法中的值
Object o3 = cc.orElseGet(() -> Optional.ofNullable("123"));
2.1.3 判定的常用方法
java
Optional<Object> cc = Optional.ofNullable(null);
// 1. 存在则返回true
boolean present = cc.isPresent();
// 2. 为null返回true
boolean empty = cc.isEmpty();
2.1.4 判定后的操作方法
java
Optional<Object> cc = Optional.ofNullable(null);
// 1. 如果对象不为空,则执行方法体的内容,否则没有任何操作
cc.ifPresent(item->{
System.out.println("不为空则执行我"+item);
});
// 2. 如果对象不为空,则执行方法体的内容,否则没有任何操作
cc.ifPresentOrElse(item->{
System.out.println("不为空则执行我"+item);
},()->{
System.out.println("为空则执行我");
});
2.2 map方法介绍
map 方法的使用跟 Stream 中的map方法一样,我的理解这里面的所有的接口方法与 Stream 中重名的用法都是一样的
java
@Data
public static class User{
private String name;
private Integer age;
}
@Test
void getMapTest(){
User user = new User();
user.setName("123");
Optional<User> optionalUser = Optional.of(user);
// 1. 直接获取 user 对象的 name 的值,这里 map 是当用户不为空的时候执行的
Optional<String> name = optionalUser.map(User::getName);
System.out.println(name.isEmpty()); // 输出 false
Optional<User> optionalUser2 = Optional.ofNullable(null);
// 2. 直接获取 user 对象的 name 的值,这里 map 是当用户不为空的时候执行的
Optional<String> name2 = optionalUser2.map(User::getName);
System.out.println(name2.isEmpty()); // 输出 true
}
2.2 其他方法
其他方法:
2.2.1 Filter 方法
filter
:此方法为的是过滤,Optional<Path> p = uris. stream().filter(uri -> !isProcessedYet(uri)).findFirst() .map(Paths::get);
我这里基本上没有用过,感觉是没有使用场景的。
2.2.2 FlatMap 方法
flatMap
: 此方法我理解是拆箱转换: 例如把 Stream<Optional<T>>
转换为 Optional<T>
java
Stream<Optional<T>> os = ....
Stream<T> s = os.flatMap(Optional::stream)
3. 常用的实例
TODO 这里后面再不吧,暂时也没有太合适的例子
4. 总结
Optional
是java8中引入的,它提供了一种更优雅和安全的方式来处理可能为空的值。主要通过 or
,orElse
, ifPresent
等函数式方法来优雅的判空,以及非空后的执行操作,这里可以减少多层的 if
判断,使代码变的优雅,但是弊端使用 函数式
方法会降低代码的可读性。并且还需要对 Lambda
有一定的了解才行。