我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java8中Optional操作的实际应用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java8中Optional操作的实际应用

简介

目的:Optional的出现主要是为了解决null指针问题,也叫NPE(NullPointerException)

外形:Optional外形酷似容器(其实它就是一个容器),只是这个容器比较特殊,因为它只能存放一个对象,运气不好的话这个对象还是个null

操作:Optional从操作上来看,又跟前面的Stream流式操作很像,比如过滤filter - 提取map等

下面我们用比较简单的例子来对比着看下,Optional的一些基础用法

正文

1. Optional是什么

Optional是一个容器,只能存放一个对象(可为null)

Optional的出现是

  • 一个是为了解决NPE问题(阿里开发手册也有提到这一点,点击可直接下载,官方链接)
  • 另一个是为了代码更加清晰可读,因为Optional这个名字的灵感就是来自英文optional(可选的),意思就是说这个对象可以为空,可以不为空

2. 没它 VS 有它

下面我们用旧代码和新代码来对比着看(所谓的新旧是以Java8为分割线)

案例1:现有C类,我们要提取C.name属性

public class OptionalDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
      // 传入null,以身试法  
      getName(null);
    }
    // 取出c.name
    public static void getName(C c){
        // 旧代码 Java8之前
        String name = (c!=null ? c.getName() : DEFAULT_NAME);
        System.out.println("old: "+name);
        // 新代码 Java8之后(下面的三个操作方法后面会介绍,这里简单了解下)
        String nameNew = Optional
            				// 工厂方法,创建Optional<C>对象,如果c为null,则创建空的Optional<C>对象
                            .ofNullable(c)
            				// 提取name,这里要注意,即使c==null,这里也不会抛出NPE,而是返回空的Optional<String>,所以在处理数据时,我们不需要担心空指针异常
                            .map(c1->c1.getName())
            				// 获取optional的属性值,如果为null,则返回给定的实参DEFAULT_NAME
                            .orElse(DEFAULT_NAME);

        System.out.println("new: "+nameNew);
    }
}
class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
  // 省略getter/setter
}

乍一看,好像Java8之前的旧代码更合适啊,只需要一个三目运算符

再看Optional操作,发现并没有那么简洁

是这样的,如果只是一层判断,那普通的if判断做起来更方便;

但是如果嵌套两层呢,比如b.getC().getName()?

下面我们就看下,两层嵌套会怎么样

例子2:现多了一个B类(依赖C类),我们要从对象B中提取C的属性name,即b.getC().getName()

public static void getName2(B b){
        // 旧代码
        String name = (b!=null ? ( b.getC()!=null ? b.getC().getName() : DEFAULT_NAME) : DEFAULT_NAME);
        // 新代码
        String nameNew = Optional
                .ofNullable(b)
                .map(b1->b1.getC())
                .map(c1->c1.getName())
                .orElse(DEFAULT_NAME);
        System.out.println(nameNew);
    }

class B{
    private C c;

    public B(C c) {
        this.c = c;
    }
  // 省略getter/setter
}

这次不管是乍一看,还是一直看,都是Optional更胜一筹

例子3:现多了一个A类(依赖B类),我们要提取a.getB().getC().getName()

等等等,省略号

意思到就行,反正要说的就是单从判空来看的话,Optional肯定是好过三目运算符的(if/else这里就不举了,它的嵌套只会更多)

3. 核心操作

因为Optional主要是操作数据(类似数据库操作),所以我们这里从数据的角度来进行分析

这里我们可以分为三种操作:保存数据、处理数据、获取数据

保存数据

  • (没有默认值)public static <T> Optional<T> of(T value) :填充 T value 到 Optional 的属性中;如果 value==null,则抛出NPE
  • (默认null)public static <T> Optional<T> ofNullable(T value) :填充 T value 到 Optional 的属性中;如果引用为null,则填充null
  • (构造一个空的Optional)public static<T> Optional<T> empty():单纯地创建一个数据为null的空Optional,即直接填充null到 Optional 的属性中【不常用】

处理数据

  • (提取)public<U> Optional<U> map(Function<? super T, ? extends U> mapper) :提取Optional中属性T的某个属性值U,并将U填充到新的Optional中并返回
  • (过滤)public Optional<T> filter(Predicate<? super T> predicate) :过滤Optional中属性T的某个属性值,符合条件则将T填充到新的Optional中并返回
  • (扁平化提取)public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper):提取Optional中属性T的某个属性Optional<U>,直接返回

获取数据

  • public T orElse(T other) :获取数据,如果数据为null,则返回T other
  • public T orElseGet(Supplier<? extends T> other):获取数据,如果数据为null,则通过函数式接口other返回一个新的数据T
  • public T get() :获取数据,如果数据为null,则报NPE【不常用】

上面这些操作中,不常用的就是get()和empty()

其他的就不举了,这里主要说下map()和flatMap()

如下图所示:

map()主要是提取Optional中的属性C的属性name,然后再包装到新的Optional

输入Optional<C>, 输出Optional<String>(即Optional<c.name>)

String nameNew = Optional
                    .ofNullable(c)
                    .map(c1->c1.getName())
                    .orElse("xxx");

flatMap()主要是提取Optional中的属性B的Optional<C>属性中的C的值,然后再包装到新的Optional

输入Optional<B>,输出Optional<C>

public class FlatMapDemo {
    private static final String DEFAULT_NAME = "javalover";

    public static void main(String[] args) {
        getName(null);
    }

    // 取出 b.c.name
    public static void getName(B b){
        C c = Optional
                .ofNullable(b)
            	// 这里扁平化处理,提取Optional<C>中的C
            	// 如果用map,则返回的是Optional<Optional<C>>
                .flatMap(b->b.getC())
                .orElse(new C("xxx"));
        System.out.println(c.getName());
    }
}

class B{
    private Optional<C> c;

    public Optional<C> getC() {
        return c;
    }

    public void setC(C c) {
        this.c = Optional.ofNullable(c);
    }
}

class C{
    private String name;

    public C(String name) {
        this.name = name;
    }
    // 省略getter/setter
}

4. 应用

从规范角度来讲,是为了代码清晰,一看用Optional<T>变量,就知道T可能为null;

从编码角度来讲,主要是应用在非空判断;但是实际场景的话,有两个

  • 没有用Optional进行包裹的参数:比如上面讲到的例子,传来的参数就是普通对象,我们就需要自己用Optional容器来包裹传来的参数,然后进行后续操作
// 取出c.name
public static void getName(C c){
    // 自己手动包装 Optional<C>
    String nameNew = Optional
        .ofNullable(c)
        .map(c1->c1.getName())
        .orElse(DEFAULT_NAME);

    System.out.println("new: "+nameNew);
}
  • 有用Optional进行包裹的参数:比如数据库查询时,我们可以用Optional来包裹查询的结果并返回,这样我们分析结果的时候,只需要通过orElse()来获取,同时还可以设定默认值
// 返回Optional<Car>,通过.orElse(defaultCar)就可以获取返回值,如果返回值为null,还可以设定一个默认值defaultCar
Optional<Car> selectOne(SelectStatementProvider selectStatement);

总结

  • Optional是什么:一个容器,存放一个对象,对象可以为null

  • 没它 VS 有它:看场景

    • 如果只是单个的if/else判断,那就没它会好点;

    • 如果嵌套比较多,或者本来传来的数据就是Optional类型,那肯定是Optional合适

  • 核心操作:不常用的这里就不写了

    • 保存数据:工厂方法 of()ofNullable()
    • 处理数据:map(), filter(), flatMap()
    • 获取数据:orElse()
  • 应用:主要用在非空判断,实际场景的话,我们可以用在数据库查询语句中

总结

到此这篇关于Java8中Optional操作的文章就介绍到这了,更多相关Java8中Optional操作内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java8中Optional操作的实际应用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python语法的实际应用操作

本篇内容介绍了“Python语法的实际应用操作”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 元组用(),list用[],元祖不能修改,
2023-06-17

Python配置的实际操作及如何应用

这篇文章给大家介绍Python配置的实际操作及如何应用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Vim的默认配置对Python支持有限,可以通过安装插件等方法提高在Vim中编写Python程序的效率。< typet
2023-06-17

如何进行Python安装的实际应用操作

今天就跟大家聊聊有关如何进行Python安装的实际应用操作,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。下载windows版本,下载完成以后,双击打开,然后一步一步安装。*Pytho
2023-06-17

Python数组中实际应用的数据结构的操作分析

这期内容当中小编将会给大家带来有关Python数组中实际应用的数据结构的操作分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。本文并不详细介绍Python列表,可以参看Python文档。Python数组中
2023-06-17

Python连接在实际应用中的相关操作步骤是什么

这篇文章给大家介绍Python连接在实际应用中的相关操作步骤是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在计算机语言中Python连接经常被使用的语言,说以需要大家努力的学习相关的知识与技能更好的了解Pytho
2023-06-17

Win8.1内置的SkyDrive网盘功能应用实际操作技巧

上个月,微软向全球发布了最新的Win8.1系统,同样对自带的多款的Modern应用也进行了功能更细和整合。其中一个就是SkyDrive应用,可以说,这个网盘已经与Win8.1系统高度整合在一起,无论是本地还是云端,都能操作。SkyDrive
2022-06-04

服务器操作系统标准化:实际应用案例

服务器操作系统标准化通过统一配置、安全策略和管理流程,提升服务器管理效率,保障系统稳定性。本文以实际案例展示标准化服务器操作系统的应用实践。
服务器操作系统标准化:实际应用案例
2024-02-29

在实际工作中如何应用Brainstorm框架

Brainstorm框架是一个有助于组织思路和促进创意的工具,可以在实际工作中以以下方式应用:解决问题:当团队面临困难或挑战时,可以使用Brainstorm框架来收集大家的想法和建议,找到解决问题的方法。制定计划:在制定项目计划或商业策略时
在实际工作中如何应用Brainstorm框架
2024-03-14

SQL中笛卡尔积的实际应用

目录1.概念2.sql笛卡尔积语法2.1 表1有2条数据2.2 表2有3条数据2.3 笛卡尔积有6条数据3.sql中的应用总js结1.概念百度百科:笛卡尔乘积javascript是指在数学中,两个集合X和Y的笛卡尔积(Cartesian
2023-03-02

详解php8中注解的实际应用

详解PHP8注解的实际应用PHP8引入注解,允许添加元数据以提供额外信息。注解通过属性注解描述属性,文档注解生成文档,自定义注解提供特定应用程序元数据。广泛应用于代码文档、类型检查、框架集成、代码重用。最佳实践包括仅使用有意义的注解、遵循命名约定、验证正确使用。
详解php8中注解的实际应用
2024-04-02

Python矩阵转置的实际应用操作方案及如何编写代码

今天就跟大家聊聊有关Python矩阵转置的实际应用操作方案及如何编写代码,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。你需要确保该数组的行列数都是相同的.比如:arr = [[1,
2023-06-17

PHP中封装性的实际应用案例

导言:封装性是面向对象编程中的重要原则之一,它指的是将类的数据和方法封装在一起,以实现数据的隐藏和保护。在PHP开发中,封装性的应用非常广泛,可以帮助我们创建更加可维护、可扩展和安全的代码。本文将通过具体的案例和代码示例,展示PHP中封装性
2023-10-21

Oracle SQL中除法运算的实际应用

标题:Oracle SQL中除法运算的实际应用Oracle SQL中的除法运算在数据处理和分析中具有重要的作用,通过除法运算可以计算数据之间的比率、百分比、平均值等各种指标。本文将通过具体的代码示例介绍Oracle SQL中除法运算的实际
Oracle SQL中除法运算的实际应用
2024-03-10

Golang协程在实际项目中的应用

golang协程通过goroutine实现并发执行:创建协程:使用goroutine关键词创建协程,其本质是共享内存的执行函数。并发处理请求:在分布式文件系统中,使用协程并行处理来自多个客户端的并发请求,提升性能。并行读取文件:在一个协程中
Golang协程在实际项目中的应用
2024-04-15

MySQL时间戳的作用及实际应用案例分析

MySQL时间戳的作用及实际应用案例分析时间戳(Timestamp)在MySQL数据库中是一种非常重要且常用的数据类型,用于存储日期和时间信息。它能够记录数据的创建时间、修改时间等关键信息,对于数据的追踪、分析和管理都具有重要意义。本文将
MySQL时间戳的作用及实际应用案例分析
2024-03-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录