java8 Optional理解及示例

news2024/11/18 15:48:57

大量判空的代码

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

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

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,否则返回默认值worker2
	Worker 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,不符合则为false
	System.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.coloradmin.cn/o/1117411.html

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

相关文章

UVM 验证方法学之interface学习系列文章(八)《interface不小心引入X态问题》

前面的文章学习,想必大家都对interface 有了深入了解。大家可不要骄傲哦,俗话说:小心驶得万年船。今天,再给大家介绍一个工作中,不是经常遇到,但是一旦遇到,会让你纠结很久的事情。 前面文章提到,随着验证复杂度的不断增加,interface 的bind 的操作,是必不可少的用法…

1.1 网页的基本概念

思维导图&#xff1a; 网页设计基础知识 --- **导言&#xff1a;** 随着互联网的迅速蔓延&#xff0c;世界各地的数亿人群均可以通过网络实现聊天、购物、阅读新闻、查询天气等功能。而在幕后&#xff0c;是成千上万的网页支撑这一切。但这些网页是如何制作的&#xff1f;我们…

Unity之ShaderGraph如何实现靠近显示溶解效果

前言 今天我们来实现一个我再B站看到的一个使用LeapMotion实现的用手部触摸就可以显示的溶解效果。 效果如下图所示&#xff1a; 主要节点 Position&#xff1a;提供对网格顶点或片段的Position 的访问&#xff0c;具体取决于节点所属图形部分的有效着色器阶段。使用Space下…

无痕视频去水印方法分享-这些软件你值得拥有

怎么无痕视频去水印&#xff1f;喜欢剪视频的你是不是经常碰到这种烦人的事&#xff1f;就是每次在网上找到好看的视频素材&#xff0c;下载下来却总是带着各种各样的水印&#xff0c;这些水印不仅影响美观&#xff0c;还挡住了视频里重要的内容&#xff0c;如果你也遇到这种情…

JAVA基础-方法(5)

目录 1、方法介绍<br />2、方法的重载&#xff08;在同一个类中&#xff0c;方法名相同&#xff0c;列表参数不同&#xff08;数量不同&#xff0c;类型不同&#xff0c;顺序&#xff09;&#xff09;3、方法的重写&#xff08;方法的覆盖-参数类别相同&#xff0c;返回值…

java项目容器化(docker)部署注意点

cgroup 支持 从 jdk 8u121 开始支持&#xff0c;即低于这个版本无法使用容器特性 https://bugs.java.com/bugdatabase/view_bug.do?bug_id8170888 https://bugs.openjdk.org/browse/JDK-8170888 https://bugs.java.com/bugdatabase/view_bug.do?bug_id8175898 https://b…

EPLAN_008#3D布局图

一、新建页 多线原理图纸画好以后 打开布局空间导航器——右键——新建 二、插入箱柜 菜单栏——插入——箱柜 三、显示安装板 然后调整视角 四、插入线槽 菜单栏——插入——线槽——选择合适的线槽——确定 按A键可以切换线槽方向&#xff0c;如果位置不对&#xff0c;可以再…

redis的cluster

1.我们的哨兵模式中&#xff0c;当主节点挂掉以后&#xff0c;此时哨兵会重新进行选举&#xff0c;选举出新的主节点去对外提供写服务 在选举的过程中,他redis整个集群是不提供写服务的 &#xff08;因为此时我们哨兵对外提供写服务的只有Master&#xff09; 2.我们单节点的red…

NRK3301语音芯片在智能窗帘上的应用

窗帘是人们日常生活中所经常使用的家居产品&#xff0c;传统的窗帘大多都需要手动拉动窗帘使用&#xff1b;存在着拉拽费劲&#xff0c;挂钩容易掉落等问题。随着数字化转型的升级&#xff0c;推进了窗帘市场的高质量发展。智能窗帘也“适时出现”出现了&#xff0c;一款带有语…

CV计算机视觉每日开源代码Paper with code速览-2023.10.20

精华置顶 墙裂推荐&#xff01;小白如何1个月系统学习CV核心知识&#xff1a;链接 点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【目标检测】Click on Mask: A Labor-efficient Annotati…

Microsoft Edge中使用开源的ChatGPT

一、双击打开浏览器 找到&#xff1a;扩展&#xff0c;打开 二、打开Microsoft Edge加载项 三、Move tab新标签 获取免费ChatGPT 四、启用Move tab。启用ChatGPT。 扩展 管理扩展 启用 五、新建标签页&#xff0c;使用GPT 六、使用举例 提问 GPT回复

不想加班的小伙伴们,请把这四个神器焊在电脑上~

今天又来给大家分享干货啦&#xff0c;如果你下载视频没渠道&#xff0c;写方案没灵感思路&#xff0c;做表格太慢&#xff0c;做海报太复杂&#xff0c;那你一点要看这一篇&#xff0c;今天分享的四个宝藏网站专门解决以上问题&#xff0c;一起来看看吧&#xff01; 一、WeDow…

中文编程开发语言工具应用案例:ps5体验馆计时收费管理系统软件

中文编程开发语言工具应用案例&#xff1a;ps5体验馆计时收费管理系统软件 软件部分功能&#xff1a; 1、计时计费功能&#xff1a;只需点开始计时即可&#xff0c;时间直观显示 2、商品管理功能&#xff1a;可以管理饮料等商品 3、会员管理功能&#xff1a;支持只用手机号作…

Android---RecyclerView替代ListView

RecyclerView 简称RV&#xff0c;是作为 ListView 和 GridView 的加强版出现&#xff0c;目的是在有限的屏幕之上展示大量的内容。因此&#xff0c;RecyclerView 的复用机制的实现是它的一个核心部分。 RV 常规使用方式 // 1 RecyclerView.setLayoutManager(); // 2 Recycler…

JavaCV + FFmpeg 播放音视频

JavaCV FFmpeg 播放音视频 1、导入JavaCV库1.1 使用ffmpeg必要库1.2 简单FFmpeg命令 待续~~~~ FFmpeg documentation bytedeco/javacv - GitHub 1、导入JavaCV库 gradle下面这种会导入javacv-platform所有包&#xff0c;非常耗时&#xff1a;https://repo.maven.apache.org/…

西门子博途软件加密保护方法

一、程序块的专有技术保护 程序块的专有技术保护主要是对项目中的程序块&#xff08;OB、FB、FC、DB&#xff09;进行访问保护&#xff0c;如果没有专有技术保护密码则无法看到程序块中的具体内容&#xff0c;对于专有技术保护的 DB 块&#xff0c;如果没有密码只能读不能写。…

怎么理解函数式编程思维?

文章目录 &#xff08;2023年9.29号&#xff0c;正月十五家乡的月亮&#xff09; ​ 理解函数式编程要注重思维的转变。函数式编程聚焦于简洁的高阶函数&#xff0c;高阶函数注重封装底层运作原理来解决复杂的业务场景&#xff0c;比如 Scala、Groovy、Clojure 语言&#xff1a…

解决pip安装包后但是Pycharm检测不到

首先要知道python找包的原理&#xff1a;原理 之后把一下代码打印一下&#xff1a; import sys print(sys.executable)# /usr/bin/python2 print(sys.path)# [/usr/lib/python2.7, /usr/lib/python2.7/dist-packages, /usr/local/lib/python2.7/dist-packages] print(sys.prefi…

Leetcode—动态规划(背包问题)

1、背包基础问题&#xff1a;01背包 输入&#xff1a;背包最大重量为 4。物品重量数组weight[1,3,4]&#xff0c;对应的价值数组value[15,20,30]。 五部曲&#xff1a; 1、确定dp数组以及下标的含义 对于背包问题&#xff0c;dp采用二维数组&#xff0c;即dp[i][j]表示从下标…

第78篇:巧妙方法抓取某商用红队扫描器的4000多个漏洞利用exp

Part1 前言 大家好&#xff0c;我是ABC_123&#xff0c;本期分享一个真实案例。大约在两年前&#xff0c;有机会接触到一台红队扫描器设备&#xff08;也可以理解为渗透测试机器人&#xff09;&#xff0c;我抱着好奇的心态去那里做了一下测试&#xff0c;感觉还不错。里面大概…