一、简介

从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。
本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。
我们从一个简单的用例开始。在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException:

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();

在这个小示例中,如果我们需要确保不触发异常,就得在访问每一个值之前对其进行明确地检查:

if (user != null) {Address address = user.getAddress();if (address != null) {Country country = address.getCountry();if (country != null) {String isocode = country.getIsocode();if (isocode != null) {isocode = isocode.toUpperCase();}}}
}

这很容易就变得冗长,难以维护。为了简化这个过程,我们来看看用 Optional 类是怎么做的。从创建和验证实例,到使用其不同的方法,并与其它返回相同类型的方法相结合,下面是见证 Optional 奇迹的时刻。

二、使用Optional优点

Optional 是一个对象容器,具有以下两个特点:

  • 提示用户要注意该对象有可能为null
  • 简化if else代码

三、Optional使用

1. 创建:

Optional.empty(): 创建一个空的 Optional 实例

//返回一个Null的optional
Optional<String> empty = Optional.empty();

Optional.of(T t): 创建一个 Optional 实例,当 t为null时抛出异常

//of 方法的值不能为空否则会抛出异常
Optional<String> optional1 = Optional.of("hello");

Optional.ofNullable(T t): 创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例

//ofNullable 传入null不会异常
String str = null;
Optional<String> optional2 = Optional.ofNullable(str);

2. 获取:

get(): 获取optional实例中的对象,当optional 容器为空时报错

3. 判断:

isPresent(): 判断optional是否为空,如果空则返回false,否则返回true

orElse(T other): 如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值

orElseGet(Supplier other): 如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other

orElseThrow(Supplier exception): 如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常

4. 过滤:

filter(Predicate p): 如果optional不为空,则执行断言函数p,如果p的结果为true,则返回原本的optional,否则返回空的optional

5. 映射:

map(Function<T, U> mapper): 如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。

flatMap(Function< T,Optional> mapper): 跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional

区别: map会自动将u放到optional中,而flatMap则需要手动给u创建一个optional

四、Optional示例

public class OptionalTest {public static void main(String[] arg) {//1.创建Optional对象,如果参数为空直接抛出异常Optional<String> str=Optional.of("a");//2.获取Optional中的数据,如果不存在,则抛出异常System.out.println(str.get());//3.optional中是否存在数据System.out.println(str.isPresent());//4.获取Optional中的值,如果值不存在,返回参数指定的值System.out.println(str.orElse("b"));//5.获取Optional中的值,如果值不存在,返回lambda表达式的结果System.out.println(str.orElseGet(()->new Date().toString()));//6.获取Optional中的值,如果值不存在,抛出指定的异常System.out.println(str.orElseThrow(()->new RuntimeException()));Optional<String> str2=Optional.ofNullable(null);//7.optional中是否存在数据System.out.println(str2.isPresent());//8.获取Optional中的值,如果值不存在,返回参数指定的值System.out.println(str2.orElse("b"));//9.获取Optional中的值,如果值不存在,返回lambda表达式的结果System.out.println(str2.orElseGet(()->new Date().toString()));//10.获取Optional中的值,如果值不存在,抛出指定的异常System.out.println(str2.orElseThrow(()->new RuntimeException()));}
}

输出:

a
true
a
a
a
false
b
Mon May 15 20:22:47 CST 2022
Exception in thread “main” java.lang.RuntimeException
at OptionalTest.lambda$main3(OptionalTest.java:42)atOptionalTest3(OptionalTest.java:42) at OptionalTest3(OptionalTest.java:42)atOptionalTest$Lambda$4/931919113.get(Unknown Source)
at java.util.Optional.orElseThrow(Optional.java:290)
at OptionalTest.main(OptionalTest.java:42)

五、Optional示例

package crazy;import java.util.Optional;class Company {private String name;private Optional<Office> office;public Company(String name, Optional<Office> office) {this.name = name;this.office = office;}public String getName() {return name;}public Optional<Office> getOffice() {return office;}
}class Office {private String id;private Optional<Address> address;public Office(String id, Optional<Address> address) {this.id = id;this.address = address;}public String getId() {return id;}public Optional<Address> getAddress() {return address;}
}class Address {private Optional<String> street;private Optional<String> city;public Address(Optional<String> street, Optional<String> city) {this.street = street;this.city = city;}public Optional<String> getStreet() {return street;}public Optional<String> getCity() {return city;}
}public class OptionalDemo1 {public static void main(String[] args) {Optional<Address> address1 = Optional.of(new Address(Optional.ofNullable(null), Optional.of("New York")));Optional<Office> office1 = Optional.of(new Office("OF1", address1));Optional<Company> company1 = Optional.of(new Company("Door Never Closed", office1));// What is the street address of company1?// In which city company1 is located?Optional<Office> maybeOffice = company1.flatMap(Company::getOffice);Optional<Address> maybeAddress = office1.flatMap(Office::getAddress);Optional<String> maybeStreet = address1.flatMap(Address::getStreet);maybeStreet.ifPresent(System.out::println);if (maybeStreet.isPresent()) {System.out.println(maybeStreet.get());} else {System.out.println("Street not found.");}// shorter wayString city = company1.flatMap(Company::getOffice).flatMap(Office::getAddress).flatMap(Address::getStreet).orElse("City is not found.");System.out.println("City: " + city);// only print if city is not nullcompany1.flatMap(Company::getOffice).flatMap(Office::getAddress).flatMap(Address::getCity).ifPresent(System.out::println);}
}

JDK1.8新特性 Optional判空详解,简化判空操作相关推荐

  1. 【java8新特性】——Stream API详解(二)

    一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...

  2. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(一)概要和介绍

    前言 本文隶属于专栏<大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 目录 Spark 3.2.0 ...

  3. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(二)背景和动机

    前言 本文隶属于专栏<大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 目录 Spark 3.2.0 ...

  4. java8 stream遍历_Java8新特性:Stream流详解

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

  5. java lambda表达式详解_Java8新特性:Lambda表达式详解

    在 Java 版本的历次更新迭代中,Java8 是一个特殊的存在,与以往的版本升级不同.我们对 Java8 似乎抱有更大的期待,因为它是 Java5 之后最重要的一次升级,提供了十多个新特性,其中 L ...

  6. java lambda表达式详解_java8新特性-Lambda表达式的详解(从0开始)

    这几天复习了java8的一些新特性,作为一个从java5以来最具革命性的版本,一直没有来得及总结.本系列文章主要是从<java8实战>总结的.这是第一篇文章主要介绍java8的lambda ...

  7. H5的新特性及部分API详解

    h5新特性总览 移除的元素 纯表现的元素: basefont.big.center.font等  对可用性产生负面影响的元素: frame.frameset.noframes 新增的API 语义: 能 ...

  8. oracle中pdb,Oracle 12C新特性-CDB和PDB 详解

    最近看到好多人都在尝试Oracle中的12C新特性-容器数据库,今年3月Orcle推出了Release2版本,可以算是一个稳定版本了.下午着手尝试了一下,还是蛮不错得 1.前言 CDB与PDB是Ora ...

  9. 【Java 8 新特性】Java Clock 详解

    Java Clock 详解 systemDefaultZone millis instant offset system systemUTC tick tickMillis tickSeconds t ...

最新文章

  1. 中国电信的新媒体营销尝试
  2. IE11下载文件时出现文件名乱码
  3. 【转】TI蓝牙BLE 协议栈代码学习
  4. 求最大整数及其最小下标
  5. 【iOS XMPP】使用XMPPFramewok(一):添加XMPPFramework(XCode 4.6.2)
  6. hibernate中的一级缓存
  7. 小黑小波比.搭建个人网站
  8. jzoj3888-正确答案【字符串hash,dfs】
  9. VC创建DLL动态链接库及其调用
  10. Maven——windows下安装配置及IDEA设置本地仓库的步骤总结
  11. iso8601 转换 java_java积累----ISO8601格式时间转化为Datetime类型
  12. *SCM-MANAGER独立部署方式
  13. batchplot放到哪个文件夹_Batchplot使用技巧,转换CAD图纸格式并实现批量打印
  14. 常见排序算法的原理与实现(js)
  15. 王兴评华为造车:技术实力、忽悠能力都和特斯拉旗鼓相当;“微信键盘”开启内测;PDF 开发者去世|极客头条...
  16. hdu 2896 AC自动机
  17. 电子电路基础 (4)——电阻的认识
  18. dw整个网站html文件怎么放一起,Dreamweaver模板如何批量做网页
  19. 语音识别之wave文件(*.wav)格式、PCM数据格式介绍
  20. Linux下终端分屏利器tmux

热门文章

  1. 深圳绿道最全资料合集
  2. tp管理界面找不到服务器,我的TP-LINK路由器无法登陆管理界面
  3. 选下拉框的的值对应上传相应的图片_excel表格下拉菜单调用对应数据,如何在excel中实现,选择下拉菜单某一项,该表格中就出现选项对应的数据?...
  4. 关于泛微E9 OA系统手机端无法使用的抢救过程
  5. linux内核书籍推荐
  6. 论文阅读:FlowNet 2.0: Evolution of Optical Flow Estimation with Deep Networks
  7. Java的进化之路走到了尽头
  8. 量化投资学习——最优成交剩撤卖
  9. 解决Incorrect result size: expected 1, actual 0!
  10. 小红书种草和小红书种草笔记