Java 8特性之Optional详解

article/2025/7/28 7:30:46

一、Optional类 简介

Optional类是 Java 8 引入的一个很有趣的特性。它主要解决的问题是臭名昭著的空指针异常(NullPointerException)

  • Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
  • Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  • Optional 类的引入很好的解决空指针异常。

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

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

举一个简单的例子,在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException:

用户 -> 家庭住址  -> 城市  ->邮编
String postCode = user.getAddress().getCity().getPostCode();

在这个示例中,为了避免异常,就得在访问每一个值之前对其进行明确地检查:

if (user != null) {Address address = user.getAddress();if (address != null) {City city= address.getCity();if (city != null) {String postCode = city.getPostCode();if (postCode != null) {//对postCode进行操作test(postCode);}}}
}

这很容易就变得冗长,难以维护。
为了简化这个过程,我们就可以用 Optional 类。

二、Optional类的使用

1. 创建:

Optional类的实例创建有三种方式:

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

2. 获取:

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

3. 判断:

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

  • ifPresent(Consumer c):如果optional不为空,则将optional中的对象传给Comsumer函数

public class OptionalDemo {public static void main(String[] args) {User user = new User("王也", "5");User userNull= null;Optional<User> optional = Optional.ofNullable(user);System.out.println(optional.isPresent());optional.ifPresent(u -> System.out.println("optional不为null  "+u));}
}

在这里插入图片描述

  • orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值
   User user = new User("王也", "5");User userNull= null;//orElse的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值:User user1 = Optional.ofNullable(userNull).orElse(user);System.out.println(user1);//控制台输出:User(name=王也, age=5)
  • orElseGet(Supplier other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other
  User user1 = Optional.ofNullable(userNull).orElseGet(()->user );//结果同上
  • orElseThrow(Supplier exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常

//这个方法让我们有更丰富的语义,可以决定抛出什么样的异常,而不总是抛出 NullPointerException。User result = Optional.ofNullable(userNull).orElseThrow( () -> new IllegalArgumentException());

orElse() 和 orElseGet() 的不同之处

乍一看,这两种方法似乎起着同样的作用。然而事实并非如此。我们创建一些示例来突出二者行为上的异同。

(1)当对象为空时:

public class OptionalDemo {public static void main(String[] args) {User userNull = null;System.out.println("使用orElse():");User result = Optional.ofNullable(userNull).orElse(createNewUser());System.out.println("使用orElseGet():");User result2 = Optional.ofNullable(userNull).orElseGet(() -> createNewUser());}private static User createNewUser() {System.out.println("Creating New User");return new User("新的user对象", "1234");}
}

上面的代码中,两种方法都调用了 createNewUser() 方法,这个方法会记录一个消息并返回 User 对象。

控制台输出:

使用orElse()Creating New User
使用orElseGet()Creating New User

由此可见,当对象为空而返回默认对象时,行为并无差异。

(2)当对象不为空时:

public class OptionalDemo {public static void main(String[] args) {User user = new User("王也", "5");System.out.println("使用orElse():");User result = Optional.ofNullable(user).orElse(createNewUser());System.out.println("使用orElseGet():");User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());}private static User createNewUser() {System.out.println("Creating New User");return new User("新的user对象", "1234");}
}

控制台输出:

使用orElse()Creating New User
使用orElseGet()

这个示例中,两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。

在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。

4. 过滤:

filter(Predicate p):filter() 接受一个 Predicate 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional。

5. 映射:

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

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

map() 对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中。这就使对返回值进行链试调用的操作成为可能 —— 这里的下一环就是 orElse()。

flatMap() 也需要函数作为参数,并对值调用这个函数,然后直接返回结果。

4和5示例:

public class OptionalDemo {public static void main(String[] args) {List<Student> studentList = initData();for (Student student : studentList) {Optional<Student> studentOptional = Optional.of(student);Integer score = studentOptional.filter(s -> s.getAge() >= 18).map(Student::getScore).orElse(0);if (score > 80) {System.out.println("入选:" + student.getName());}}}private static List<Student> initData(){Student s1 = new Student("张三", 19, 80);Student s2 = new Student("李四", 19, 50);Student s3 = new Student("王五", 23, null);Student s4 = new Student("赵六", 16, 90);Student s5 = new Student("钱七", 18, 99);Student s6 = new Student("孙八", 20, 40);Student s7 = new Student("吴九", 21, 88);return Arrays.asList(s1, s2, s3, s4, s5, s6, s7);}
}

使用stream流的写法:

 public static void main(String[] args) {List<Student> studentList = initData();List<String> studentName = studentList.stream().filter(student -> student.getAge() >= 18).filter(student -> student.getScore() != null && student.getScore() > 80).map(student -> student.getName()).collect(Collectors.toList());System.out.println(studentName);}

控制台输出:

入选:钱七
入选:吴九

http://chatgpt.dhexx.cn/article/Nmf5dt0B.shtml

相关文章

Java基础之java8 新特性

Java基础之java8 新特性 一、Lambda 表达式二、Stream 初体验三、方法引用四、默认方法五、Optional 类六、Base 64七、字符串拼接八、 equals 与 instanceof九、final 一、Lambda 表达式 Lambda 表达式是在 Java8 中引入的&#xff0c;并号称是 Java8 的最大的特点。Lambda 表…

java8新特性Lambda和Stream以及函数式接口等新特性介绍

主要内容 1.Lambda 表达式 2.函数式接口 3.方法引用与构造器引用 4.Stream API 5.接口中的默认方法与静态方法 6.新时间日期API 7.其他新特性 Java 8新特性简介 速度更快速度更快代码更少&#xff08;增加了新的语法Lambda 表达式&#xff09;强大的Stream API便于并行最大化…

python 读取并显示图片的两种方法

转自&#xff1a;http://www.cnblogs.com/yinxiangnan-charles/p/5928689.html 在 python 中除了用 opencv&#xff0c;也可以用 matplotlib 和 PIL 这两个库操作图片。本人偏爱 matpoltlib&#xff0c;因为它的语法更像 matlab。 一、matplotlib 1. 显示图片 import matplotli…

Python同时显示多张图片在一个画面中(两种方法)

很多时候需要把很多图片同时显示到一个画面中&#xff0c;现在分享两个方法&#xff0c;这里我恰好拿之前写的爬取网上图片保存到本地的爬虫模型爬一些图片作为素材Python 爬虫批量爬取网页图片保存到本地。 得到素材如下所示&#xff1a; 现在让这些图片同时显示。 方法一 …

python 打开 显示图片

import matplotlib.pyplot as plt # plt 用于显示图片 from PIL import Imageplt.figure() plt.plot([1,2], [1,2])plt.rcParams[font.sans-serif] [SimHei] # 中文乱码 plt.imshow(Image.open("b.png"))plt.axis(off)plt.tight_layout() manager plt.get_current…

python 把matplotlib绘制的图片显示到html中

需求 一般网页中图片显示是给url链接过去&#xff0c;但是有的时候显示的图表是临时计算绘制的&#xff0c;并不需要保存&#xff0c;因此就需要直接显示一个图片的方法。 灵感是来自于jupyter&#xff0c;发现他是这样的&#xff1a; 估计是base64编码了。 查了一下如何把ma…

python如何将图片显示在网页上

from flask import Flask, render_template_string import base64 import cv2import osapp Flask(__name__)# 读取图像app.route(/)def index():# 读取图像文件并将其转换为Base64编码的字符串img_path 1.pngimg_data open(img_path, rb).read()img_base64 base64.b64encod…

python matplotlib 显示图像

python matplotlib 显示图像 首先需要import import os from PIL import Image import matplotlib.pyplot as plt 显示一幅彩色图片 img Image.open(os.path.join(images, 2007_000648 .jpg))plt.figure("Image") # 图像窗口名称 plt.imshow(img) plt.axis(on)…

python中plt.imshow()不显示图片

python画图函数可能是需要一些设置&#xff0c;或者一些特定的函数运行才会出现图片的。 Python中plt.imshow(image)无法显示图片解决办法 使用plt.imshow()发现不能显示图片&#xff0c;加了plt.show()也还是不能显示 先引入包pylab import pylab 然后在plt.imshow(img)后面…

Python tkinter之PhotoImage图片显示问题

作为Python小白的你&#xff0c;有没有遇到过这几个问题&#xff1f; PhotoImage不支持jpg等图片格式&#xff1b;将PhotoImage放在函数里图片不显示&#xff1b;循环加入图片只显示一张&#xff1b; 这些难倒了一大批小白&#xff0c;那么接下来&#xff0c;本文教你如何解决…

python图显示在新的窗口_python在新的图片窗口显示图片(图像)的方法

python在新的图片窗口显示图片(图像)的方法 使用python画图,发现生成的图片在console里。不仅感觉很别扭,很多功能也没法实现(比如希望在一幅图里画两条曲线)。 想像matlab一样单独地生成一个图片窗口,然后我在网上找了一个多小时,都没有找到想要的,要么仅仅是画图的教…

python人工智能-动态显示图片的几种办法实现

python人工智能动态显示图片 任务简介&#xff0c;在电脑创建一个文件加&#xff0c;利用代码往文件加入照片文件&#xff0c; 然后动态显示该文件夹中的照片&#xff0c;显示给用户观看&#xff0c;可以利用open-cv&#xff0c;matplotlib,PIL等技术实现 这里是电脑一个装有照…

Python 3 显示图像的方法

如果你正在寻找一个库来帮助你在 Python 中显示图像&#xff0c;那么你很幸运。Python 有许多不同的库可用于显示图像。三个最受欢迎的库是Pickel、Matplotlib 和 OpenCV。 到底应该选哪一个&#xff0c;还是看自己的个人喜好了。我喜欢并使用 OpenCV 而不是 Pillow 和 Matplot…

python显示图片_python图像显示

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 使用python进行数字图片处理,还得安装pillow包。 虽然python里面自带一个pil(python images library), 但这个库现在已经停止更新了,所以使用pillow, 它是由p…

python显示图片

python显示图片两种方法 1.利用Pillow包 未安装的可以通过pip install Pillow安装 from PIL import Image img Image.open(notMNIST_large/A/aGFua28udHRm.png) img.show() 显示的图片如下&#xff1a; 2.利用matplotlib 同样可以通过pip进行安装 from PIL import Image …

使用Python查看并显示图像

今天又来写一个Python的基础用法&#xff0c;使用Python来显示图像&#xff0c;不多说&#xff0c;代码如下&#xff1a; import matplotlib.pyplot as plt from matplotlib.image import imreadimg imread(C:/Users/xx/Desktop/xx.jpg) plt.imshow(img)plt.show() 2022.05.1…

基于python多光谱遥感数据处理、图像分类、定量评估及机器学习方法应用

普通数码相机记录了红、绿、蓝三种波长的光&#xff0c;多光谱成像技术除了记录这三种波长光之外&#xff0c;还可以记录其他波长&#xff08;例如&#xff1a;近红外、热红外等&#xff09;光的信息。与昂贵、不易获取的高光谱、高空间分辨率卫星数据相比&#xff0c;中等分辨…

推扫式和快照式高光谱成像系统在红肉掺假检测中的应用

目录 摘要 推扫式高光谱成像系统的应用 快照式高光谱成像系统的应用 总结 参考文献 摘要 肉类掺假常见于用低价肉代替高价肉获取非法利益&#xff0c;它不但影响了食品的质量&#xff0c;甚至会威胁到人们的健康。目前的检测手段一般是取样后送样检测&#xff0c;很难实时…

不同光谱信息的图像比较

首先&#xff0c;我们要知道普通光学相机在自然光下拍的照片其实并不包含完整的光谱信息&#xff0c;一般在遥感领域&#xff0c;多/高光谱数据应该包含近红外波段&#xff0c;例如Landsat有如下波段&#xff1a; 编号 波长&#xff08;m&#xff09; 1 0.433–0.453 深蓝/紫…

双目多光谱融合_Matlab标定+OpenCV

1.标定注意事项 (1)标定板平整度 (2)棋盘格&#xff0c;圆&#xff08;偏心误差&#xff09;&#xff1b;精度&#xff1a;圆>棋盘格&#xff0c;前提条件优化偏心误差 (3)所有标定数据加一起尽量布满整个视野 (4)左右相机采用近处标定数据分别进行单目标定&#xff0c;…