java8 Optional理解及示例

大量判空的代码

实际中,对象不判空会导致空指针异常。

为了规避为指针,不得不写出这种非常冗长又丑陋的空指针判断。

public void tooMuchNull(Worker worker) {if (worker != null) {Address address=worker.getAddress();if (address != null) {String city=address.getCity();}}
}

Optional<T>

Optional<T>包含的对象value可能非null,也可能为null。

常建的构建Optional<T>对象的方法,有ofNullable(T value)、of(T value)。

构建时,最终都会调用Optional的构造方法Optional(T value)。

而常见的判断Optional结果的方法有,orElse()、ifPresent()、get()、empty()、map()、flatMap()。

api图

如下图所示:

代码示例:

  • orElse():
/*** orElse(默认值),如果Optional<T>封装的对象不存在值,则返回默认值。*/
public void orElseDemo() {
//		Worker worker1=new Worker("123",18,"lin");Worker worker1 = null;Worker worker2 = new Worker("456", 28, "chen");//如果worker1不为null,则orElse返回worker1,否则返回默认值worker2Worker result = Optional.ofNullable(worker1).orElse(worker2);//相当于以下代码:
//		if (worker1 != null) {
//			result = worker1;
//		} else {
//			result = worker2;
//		}System.out.println(result.getName() + "," + result.getAge());
}
  • orElseGet():
/*** orElseGet(),如果Optional<T>封装的对象不存在值,则执行Supplier函数式。* orElseGet(Supplier<? extends T> other),返回的类型必须和Optional封装的对象类型一致。*/
public void ofElseGetDemo() {String name1 = null;String name2 = "lin";//orElseGet(Supplier<? extends T> other),返回的类型必须和Optional封装的对象类型一致。String result = Optional.ofNullable(name1).orElseGet(()-> name2+"def");System.out.println(result);
}
  • of():
/*** of(对象),如果封装的对象为空,则会报出空指针异常*/
public void ofDemo() {
//		Worker worker1=new Worker("123",18,"lin");Worker worker1 = null;Worker worker2 = new Worker("456", 28, "chen");Worker result = Optional.of(worker1).orElse(worker2);System.out.println(result.getName() + "," + result.getAge());
}
  • isPresent():
/*** isPresent()表示如果Optional<T>封装的对象不为空,就返回true。*/
public void isPresentDemo() {Worker worker1 = new Worker("123", 18, "lin");Optional<Worker> workerOpt = Optional.ofNullable(worker1);//这种写法比较丑,可以直接用下面的ifPresent()方法代替。boolean isPresent = workerOpt.isPresent();if (isPresent) {System.out.println(workerOpt.get().getName());}//以上代码,相当于:
//		if (worker1 != null) {
//			System.out.println(worker1.getName());
//		}
}
  • ifPresent(lambda):
/*** ifPresent(lambda)表示如果对象不为null,则会执行对应的lambda语句。*/
public void ifPresentDemo() {
//		Address address=new Address("中国","广东","深圳");
//		Worker worker1=new Worker("123",18,"lin",address);Worker worker1 = new Worker("123", 18, "lin");
//		Worker worker1=null;List<String> nameList = new ArrayList<>();Optional.ofNullable(worker1).ifPresent(worker -> nameList.add(worker.getName()));//上面这句代码的作用相当于以下注释的代码:
//		if (worker1 != null) {
//			nameList.add(worker1.getName());
//		}nameList.forEach(System.out::println);
}
  • map(lambda):

map的参数里面是lambda表达式,会从Optional对象中进行映射,提取和转换值。
map是一个非常实用的方法。用得也比较多。
比如:

String name = "";
if (person!=null) {name = person.getName();
}

这种大量的判空在项目开发中随处可见。可以使用 Optional的 map方法替换。

String name = Optional.ofNullable(person).map(Person::getName).orElse("");

其他示例:

public  void mapDemo() {String str=" test ";Optional.ofNullable(str).map(String::trim).filter(t -> t.length()> 1).ifPresent(s->{s+="1234";System.out.println(s);});
//相当于以下代码:
//	if (str != null) {
//	    str=str.trim();
//	    if (str.length() > 1) {
//		str+="1234";
//		System.out.println(str);
//	    }
//	}
}
  • flatMap(lambda):

flatMap()的参数是lambda表达式,返回值是Optional。

/*** flatMap(),如果Optional封装对象不为空,就会执行对应的mapping函数,返回Optional类型的值,否则就返回一个空的Optional对象。* 通过flatMap(),可以不断地返回Optional对象,一直进行链式调用。非常重要~*/
public void flatMapDemo() {Address address = new Address("中国", "广东", "深圳");Worker worker = new Worker("123", 18, "lin", address);String city = Optional.ofNullable(worker).flatMap(Worker::getAdress).flatMap(Address::getCity).orElse("default");System.out.println(city);
}
  • orElseThrow():
/*** orElseThrow(),如果Optional封装的对象为空,就会抛出对应的异常。*/
public void orElseThrowDemo() {
//		Worker worker = new Worker("123", 18, "lin");Worker worker = null;Worker result = Optional.ofNullable(worker).orElseThrow(IllegalArgumentException::new);System.out.println(result.getName());
}
  • filter(lambda):
public void filterDemo() {Worker worker = new Worker("123", 18, "lin");Optional<Worker> result = Optional.ofNullable(worker).filter(worker1 -> worker1.getAge() > 20);//如果符合条件(比如,年龄大于20)则为true,不符合则为falseSystem.out.println(result.isPresent());
}

区别:

  • of() 和 ofNullable() 的区别:

这两个方法都可以创建包含值的 Optional。
不同之处在于如果你把 null值作为参数传递进ofNullable(),而传递null作为参数时,of() 方法会抛出 NullPointerException。

  • orElse()和orElseGet()的区别:
    orElse(默认值),表示如果有值则返回该值,否则返回传递给它的默认值。

orElseGet(lambda表达式)会在有值的时候返回值,如果没有值,它会执行作为参数传入的函数式接口(返回类型必须和Optional封装的对象是同一种类型),并将返回其执行结果。

需要特别注意的是:

Optional的orElse()若方法不是纯计算型的,有与数据库交互或者远程调用的,都应该使用orElseGet() 。

orElse()无论前面Optional容器是null还是non-null,都会执行orElse里的方法,orElseGet()并不会。

详情参见:https://blog.csdn.net/weixin_30437337/article/details/95443798

  • isPresent()和ifPresent(lambda)的区别:

看方法名is开头,就可以知道isPresent()返回的是布尔值。而ifPresent()则是如果对应的值存在,就会执行函数式接口。

  • flatMap(lambda)和map(lambda)的区别:

值不为空时,两者都会执行参数中的函数式接口。

而flatMap()返回值是Optional,通过不断地产生Optional,可以进行链式调用。

可以重构的示例:

回头看一下开头的代码,如下:

public void tooMuchNull(Worker worker) {if (worker != null) {Address address=worker.getAddress();if (address != null) {String city=address.getCity();}}
}

下面尝试用Optional改写。

重写getter()

重写getter,返回Optional对象。

public class User {private Address address;public Optional<Address> getAddress() {return Optional.ofNullable(address);}// ...
}

优化

重写完getter后,上面的例子,可以用Optional改写为:

public void preventNullPointer() {Worker worker = new Worker("123", 18, "lin");String result = Optional.ofNullable(worker).flatMap(u -> u.getAddress()).flatMap(a -> a.getCity()).orElse("default");}

再进一步简写成:

String city = Optional.ofNullable(worker).flatMap(Worker::getAdress).flatMap(Address::getCity).orElse("default");

使用Optional要注意:

  • Optional 主要用作返回类型。

  • Optional不能作为入参的参数.

  • Optional不会序列化,不要直接作为对象属性。

  • Optional不要用于集合操作。空集合请使用Collections.emptyList()。

代码地址:

https://github.com/firefoxer1992/JavaDemo/tree/master/src/main/java/com/java8

参考资料:

https://www.cnblogs.com/zhangboyu/p/7580262.html

https://juejin.im/post/5e66ecdc518825490d126a16

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/112976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react-router-dom v6版本实现Tabs路由缓存切换

目录 文章目录 概要 效果 完整代码 概要 摆了半年摊&#xff0c;好久没写代码了&#xff0c;今天有人问我怎么实现React-Router-dom类似标签页缓存。后面看了一下router的官网。很久以前用的是react-router v5那个比较容易实现。v6变化挺大&#xff0c;但了解react的机制和rea…

Android一些新的技术栈,你都会哪些?

Jetpack Compose&#xff1a; Jetpack Compose是一种全新的声明式UI框架&#xff0c;用于构建Android应用的用户界面。它使UI开发更加简单和直观&#xff0c;通过使用Kotlin语言来创建交互式和动态的UI组件。 Kotlin Multiplatform&#xff1a; Kotlin Multiplatform允许开发者…

2023年【北京市安全员-A证】考试报名及北京市安全员-A证考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 北京市安全员-A证考试报名根据新北京市安全员-A证考试大纲要求&#xff0c;安全生产模拟考试一点通将北京市安全员-A证模拟考试试题进行汇编&#xff0c;组成一套北京市安全员-A证全真模拟考试试题&#xff0c;学员可…

【LeetCode】59. 螺旋矩阵 II

1 问题 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 示例 2&#xff1a; 输入&#xff1a;n…

windows 11 安装PHP8.2

环境说明 windows:windows 11 x64apache: Apache/2.4.43php :php-8.2.11 一.php 1、PHP下载 PHP For Windows: Binaries and sources Releases 注意&#xff1a; 1.要下载Thread Safe&#xff0c;否则没有php8apache2_4.dll这个文件&#xff1b;如果使用Apache作为服务器…

SpringSecurity+ Oauth2.0+JWT 0-1

这里写目录标题 准备工作准备SQL添加用户添加依赖准备UserInfoUserMapperUserServiceUserServiceImpl配置SpringDataUserDetailsService 授权服务器&#xff1a;AuthorizationServer配置客户端详细信息管理令牌定义TokenConfig定义AuthorizationServerTokenServices 令牌访问端…

Python爬虫基础之Selenium详解

目录 1. Selenium简介2. 为什么使用Selenium&#xff1f;3. Selenium的安装4. Selenium的使用5. Selenium的元素定位6. Selenium的交互7. Chrome handless参考文献 原文地址&#xff1a;https://program-park.top/2023/10/16/reptile_3/ 本文章中所有内容仅供学习交流使用&…

左连接一对多的情况

左连接一对多时候&#xff0c;应该以主表唯一数据为左表 GROUP_CONCAT&#xff08;&#xff09;

Flutter之Widget生命周期

目录 初始化构造函数initStatedidChangeDependencies 运行时builddidUpdateWidget 组件移除deactivatedisposereassemble 函数生命周期说明&#xff1a;实际场景App生命周期 前言&#xff1a;生命周期是一个组件加载到卸载的整个周期&#xff0c;熟悉生命周期可以让我们在合适的…

父组件与子组件的属性透传

透传是vue中一种特性&#xff0c;官方的解释是&#xff1a;“透传 attribute”指的是传递给一个组件&#xff0c;却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。这句话解释过来就是一些不被prop定义的属性直接…

尚硅谷Flink(完)FlinkSQL

&#x1f9d9;FlinkSQL&#x1f3c2;&#x1f93a; Table API 和 SQL 是最上层的 API&#xff0c;在 Flink 中这两种 API 被集成在一起&#xff0c;SQL 执行的对象也是Flink 中的表&#xff08;Table&#xff09;&#xff0c;所以我们一般会认为它们是一体的。 SQL API 是基于…

短视频矩阵系统源头开发

一、智能剪辑、矩阵分发、无人直播、爆款文案于一体独立应用开发 抖去推----主要针对本地生活的----移动端(小程序软件系统&#xff0c;目前是全国源头独立开发)&#xff0c;开发功能大拆解分享&#xff0c;功能大拆解&#xff1a; 7大模型剪辑法&#xff08;数学阶乘&#x…

openHarmony UI开发

常用组件和布局方式 组件 ArkUI有丰富的内置组件&#xff0c;包括文本、按钮、图片、进度条、输入框、单选框、多选框等。和布局一样&#xff0c;我们也可以将基础组件组合起来&#xff0c;形成自定义组件。 按钮&#xff1a; Button(Ok, { type: ButtonType.Normal, stateEf…

C# Onnx Yolov8 Detect 烟雾检测

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace Onnx…

用Python解析HTML页面

用Python解析HTML页面 文章目录 用Python解析HTML页面HTML 页面的结构XPath 解析CSS 选择器解析简单的总结 在前面的课程中&#xff0c;我们讲到了使用 request三方库获取网络资源&#xff0c;还介绍了一些前端的基础知识。接下来&#xff0c;我们继续探索如何解析 HTML 代码&…

Python超入门(5)__迅速上手操作掌握Python

# 20.列表# 一维列表 names [Hash, Bob, Nick] print(names) # 全打印 print(names[:]) # 全打印 print(names[1:3]) # 打印1到2号索引 print(names[:2]) # 打印0到1号索引[Hash, Bob, Nick] [Hash, Bob, Nick] [Bob, Nick] [Hash, Bob]# 二维列表:一维列表中嵌套一维列表…

R语言:因子分析 factor analysis

文章目录 因子分析数据集处理步骤主成分法做因子分析最大似然法做因子分析 因子分析 因子分析的用途与主成分分析类似&#xff0c;它也是一种降维方法。由于因子往往比主成分更易得到解释&#xff0c;故因子分析比主成分分析更容易成功&#xff0c;从而有更广泛的应用。 从方法…

微前端二:qiankun

qiankun是基于Single-spa开发的框架&#xff0c;所以我们先来看下Single-spa是怎么做的&#xff1a; Single-spa 是最早的微前端框架&#xff0c;兼容多种前端技术栈&#xff0c;是一个将多个单页面应用聚合为一个整体应用的 JavaScript 微前端框架&#xff1b; 优点&#xf…

APP应用开发sdk版本过低可能性原因问题排查及解决方案

同学们&#xff0c;在移动 app 开发中&#xff0c;提示sdk版本过低缺找不到原因的情况都知道的吧哈哈哈&#xff0c;这个我觉得我有必要全面的分析和排查&#xff0c;让同学们看完这个文章都得以解决。这是我的初衷奈何地主家里也没有余粮呀&#xff08;我也不能完全总结出来&a…

《动手学深度学习 Pytorch版》 8.7 通过时间反向传播

8.7.1 循环神经网络的梯度分析 本节主要探讨梯度相关问题&#xff0c;因此对模型及其表达式进行了简化&#xff0c;进行如下表示&#xff1a; h t f ( x t , h t − 1 , w h ) o t g ( h t , w o ) \begin{align} h_t&f(x_t,h_{t-1},w_h)\\ o_t&g(h_t,w_o) \end{ali…