一文了解java中Optional

文章目录

  • [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 有一定的了解才行。

相关推荐
全栈凯哥10 分钟前
桥接模式(Bridge Pattern)详解
java·设计模式·桥接模式
PXM的算法星球13 分钟前
【软件工程】面向对象编程(OOP)概念详解
java·python·软件工程
两点王爷14 分钟前
springboot项目文件上传到服务器本机,返回访问地址
java·服务器·spring boot·文件上传
小吕学编程17 分钟前
ES练习册
java·前端·elasticsearch
qsmyhsgcs29 分钟前
Java程序员转人工智能入门学习路线图(2025版)
java·人工智能·学习·机器学习·算法工程师·人工智能入门·ai算法工程师
云心似我心^o^4051 小时前
使用POI和EasyExcel使用导入
java
我是大头鸟1 小时前
SpringMVC 使用thymeleaf 进行数据展示
java·springmvc·thymeleaf
小刘|1 小时前
JVM 自动内存管理
java·jvm·算法
2401_837088501 小时前
eclipse怎么导入junit4
java·junit·eclipse
幼儿园口算大王1 小时前
Spring反射机制
java·spring·反射