Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >告别丑陋判空,一个 Optional 类搞定

告别丑陋判空,一个 Optional 类搞定

原创
作者头像
Java秦师兄
发布于 2022-10-21 07:31:24
发布于 2022-10-21 07:31:24
81900
代码可运行
举报
文章被收录于专栏:Java技术分享栈Java技术分享栈
运行总次数:0
代码可运行

概述

最近项目组内做 code review,充斥着大量的、原始的、丑陋的判空语句,大致类似下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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();
            }
        }
    }
}

让整体的代码显得十分的臃肿庞大丑陋,那么怎么办呢?其实一行代码就可以搞定:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String result = Optional.ofNullable(user)
    .map(u -> u.getAddress())
    .map(a -> a.getCountry())
    .map(c -> c.getIsocode())
    .orElse("default");

利用 Optional 这个 jdk8 中引入的类就可以优雅的处理,现在我们来详细讲解下这个类的使用和源码。

创建 Optional 实例

Optional 类, 是对 value 值进行了包装,它的值可能是 null, 也可能不是 null,一共有两个方法创建 Optional 实例

  1. static Optional of(T value)

说明: 传入的 value 为 null,会抛错,也就是说 value 不许不为 null

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testOf() {
    Integer value = 2;
    // 正常
    Optional<Integer> op = Optional.of(value);

    value = null;
    // 报空指针
    op = Optional.of(value);
}

源码:

  1. static Optional ofNullable(T value)

说明: 传入的 value 可能是 null, 也可能不是 null

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
    public void testOfNullable() {
        Integer value = 2;
        // 正常
        Optional<Integer> op = Optional.ofNullable(value);
        value = null;
        // 不报错
        op = Optional.ofNullable(value);
    }

源码:

获取 Optional 中的值

以前创建了 Optional 实例,现在你可能要获取里面的 value, 有下面几个方法。

  1. T get()

说明: 最朴素的获取原生 value 的方法,如果 value 是空,则直接抛出异常,否则返回。

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testGet() {
    Integer value = 2;
    // 正常
    Optional<Integer> op = Optional.ofNullable(value);
    Integer opVal = op.get();
    Assert.assertEquals(opVal, value);
    
    op = Optional.ofNullable(null);
    // 会抛出异常
    op.get();
}

源码:

  1. T orElse(T other)

说明: 如果值存在返回,否则返回 orElse 中传入的 other

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testOrElse() {
    // 正常
    Optional<Integer> op = Optional.ofNullable(2);
    Integer opVal = op.orElse(3);
    Assert.assertEquals(opVal, new Integer(2));

    op = Optional.ofNullable(null);
    // 为空,则返回3
    opVal = op.orElse(3);
    Assert.assertEquals(opVal, new Integer(3));
}

源码:

  1. T orElseGet(Supplier<? extends T> other)

说明: 如果存在则返回该值,否则调用 other 这个函数编程并返回该调用的结果。

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testOrElseGet() {
    // 正常
    Optional<Integer> op = Optional.ofNullable(2);
    Integer opVal = op.orElseGet(()-> {
        return new Integer(3);
    });
    Assert.assertEquals(opVal, new Integer(2));

    op = Optional.ofNullable(null);
    // 为空,则返回3
    opVal = op.orElseGet(()-> {
        return new Integer(3);
    });
    Assert.assertEquals(opVal, new Integer(3));
}

源码:

问题: orElseGet 和 orElse 有什么区别吗?

orElse() 和 orElseGet() 的不同之处在于当 ofNullable() 传入参数不为空时,orElse() 方法仍然创建了 other 这个 对象。与之相反,orElseGet() 方法不创建对象。在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。

而且我们还可以在 orElseGet 方法中加些日志,可以把这种为空的异常情况暴露出来。

  1. T orElseThrow(Supplier<? extends X> exceptionSupplier)

说明: 如果存在则返回该值,否则为空的话可以抛出自定义的异常。

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testOrElseThrow() {
    Optional<Integer> op = Optional.ofNullable(null);
    // 为空,则抛出指定的异常类型
    Integer opVal = op.orElseThrow(()-> {
        return new RuntimeException();
    });
    // 或抛出runtime异常
    Assert.assertEquals(opVal, new Integer(3));
}

源码:

判断 Optional 是否为空

  1. boolean isPresent()

说明: 判断 value 是否为空

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testIsPresent() {
    Optional<Integer> op = Optional.ofNullable(null);
    // 为空
    Assert.assertFalse(op.isPresent());
}

源码:

  1. void ifPresent(Consumer<? super T> consumer)

说明: 如果存在值,则调用对应的 consumer 方法,否则不执行任何操作。

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testIfPresent() {
    Optional<Integer> op = Optional.ofNullable(5);
    op.ifPresent(value -> {
        // 如果存在,打印出来
        System.out.println(value);
    });
}

源码:

Optional 中的过滤、转换方法

此外 Optional 额外还提供了一些过滤、转换的方法。

  1. Optional filter(Predicate<? super T> predicate)

说明: 对 Optional 中的 value 进行过滤,如果不匹配,返回空

演示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testFilter() {
    // 不满足过滤条件,返回空 Optional
    Optional<String> op = Optional.ofNullable("10").filter(item -> "15".equals(item));
    Assert.assertFalse(op.isPresent());
}

源码:

  1. Optional map(Function<? super T, ? extends U> mapper)

说明: 对 Optional 中的 value 进行转换映射为另外一个对象,如果 value 为空,返回 empty Optional

演示:

源码:

小结: 回到概述的案例,就是通过不断的 map, 链式调用返回内层对象的值。

  1. Optional flatMap(Function<? super T, Optional> mapper)

说明: 接受一个返回值为 Optional 的映射函数参数,该返回值亦是 flatMap 方法的返回值若结果为空,则返回 空 Optional。它也 map 的区别,我们用一个例子演示出来。

演示:

源码:

小结: 如果对于返回值非 Optional 类型,可以用 map 方法, 否则使用 flatMap 更加方便

总结

本文讲解了 Optional 这个类的使用和源码,非常的简单,实用,大家可以在自己的项目中用起来了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
还在用又臭又长的多层 if 判断空值?那我推荐你使用 Optional
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2024/02/06
1.9K0
Java8 中的真的 Optional 很强大,你用对了吗?
从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
Java小咖秀
2021/06/08
8360
Java8 中的真的 Optional 很强大,你用对了吗?
java8 新特性 -Optional的常见用法
用户7630333
2023/12/07
5500
Java 8 新特性 Optional 类学习/应用,NullPointerException空值检测
JDK1.8开始引入的特性,Optional 类主要解决空指针异常(NullPointerException)问题。
鳄鱼儿
2024/05/22
1780
Java 8 新特性 Optional 类学习/应用,NullPointerException空值检测
了解、接受和利用Java中的Optional (类)
作者:EUGEN PARASCHIV 译者:海松 原题: Understanding, Accepting and Leveraging Optional in Java 编者按:Java 9终于在9月21号发布,于是知乎上关于“现在Java初学用等Java9出来再学吗”之类的问题可能有更新。在 Java 8 引入Optional特性的基础上,Java 9 又为 Optional 类增加了三种方法:or()、ifPresentOrElse() 和 stream(),本文的最后,也针对这些新特性做了一些说明和
yuanyi928
2018/03/30
1.3K0
了解、接受和利用Java中的Optional (类)
JDK8中新增的Optional工具类真的很好用哦,建议收藏
  最近刚好有空给大家整理下JDK8的特性,这个在实际开发中的作用也是越来越重了,本文重点讲解下Optional
用户4919348
2021/06/10
6250
JDK8中新增的Optional工具类真的很好用哦,建议收藏
Java8新特性探索之Optional类
身为一名Java程序员,大家可能都有这样的经历:调用一个方法得到了返回值却不能直接将返回值作为参数去调用别的方法。我们首先要判断这个返回值是否为null,只有在非空的前提下才能将其作为其他方法的参数。之前,Google Guava项目曾提出用Optional类来包装对象从而解决NullPointerException。受此影响,JDK8的类中也引入了Optional类,在新版的SpringData Jpa和Spring Redis Data中都已实现了对该方法的支持。Optional是可以包含或不包含非null值的容器对象,如果存在值,则isPresent()将返回true,而get()将返回该值。
用户1289394
2020/12/08
5370
Java8新特性:Optional类的正确使用姿势
空指针异常是我们在实际开发中经常会遇到的问题,为了防止程序因为异常而中断,通常要在代码中添加大量的非空验证,例如一个释放 JDBC 相关资源的代码,如下所示。
南风
2019/08/01
9630
Java8新特性:Optional类的正确使用姿势
Java 中的 Optional
从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。
BUG弄潮儿
2020/11/11
5090
【小家java】java8新特性之---Optional的使用,避免空指针,代替三目运算符
空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,使得我们就不用显式进行空值检测
YourBatman
2019/09/03
2.6K0
Java8新特性之Optional类
我们从一个简单的用例开始。在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException:
Remember_Ray
2020/08/03
5550
Guava学习笔记(1) --- Optional类的基本使用
/** * Optional测试类 */ public class OptionalTest { @Test public void test() { //创建空的Optional对象 Optional.empty(); //使用非null值创建Optional对象,不能传入null,负责会报错 //Optional.of(null); Optional.of("123"); //使用任意值创建Optional对象 Optional<Objec
挽风
2021/04/13
3620
Java8 判空新写法!真优雅!
哈喽,小伙伴们好呀。我是狗哥,在文章的开头,说下老生常谈的 NPE 问题,NPE 问题就是:我们在开发中经常碰到的NullPointerException假设我们有两个类,他们的UML类图如下图所示
JavaFish
2022/04/18
3.9K0
Java8 判空新写法!真优雅!
JAVA8之妙用Optional解决判断Null为空的问题
在文章的开头,先说下NPE问题,NPE问题就是,我们在开发中经常碰到的NullPointerException.假设我们有两个类,他们的UML类图如下图所示
Java编程指南
2019/08/02
7.9K0
JAVA8之妙用Optional解决判断Null为空的问题
给女朋友讲解什么是Optional【JDK 8特性】
前两天带女朋友去图书馆了,随手就给她来了一本《与孩子一起学编程》的书,于是今天就给女朋友讲解一下什么是Optional类。
Java3y
2018/12/18
3520
给女朋友讲解什么是Optional【JDK 8特性】
还在用 if(obj!=null) 做非空判断?带你快速上手 Optional 实战性理解!
相信不少小伙伴已经被java的NPE(Null Pointer Exception)所谓的空指针异常搞的头昏脑涨,有大佬说过“防止 NPE,是程序员的基本修养。”但是修养归修养,也是我们程序员最头疼的问题之一,那么我们今天就要尽可能的利用Java8的新特性 Optional来尽量简化代码同时高效处理NPE(Null Pointer Exception 空指针异常)
JAVA葵花宝典
2020/06/04
8.4K0
Java-Optional类源码分析
我们在对象调用对象的方法、域的时候总是要进行判断对象是否为空的操作,即空指针异常(NullPointerException)。 本质上,这是一个包含有可选值的包装类,这意味着 Optional类既可以含有对象也可以为空。 Optional是Java8提出的新特性,就是为解决空指针异常,方便函数式编程的新特性。
Fisherman渔夫
2020/02/18
6070
设计模式实战-空对象模式,你肯定不知道,但是项目中会常用到到
受 GOF(Gang of Four,四人组)《设计模式》一书的影响,让人误以为设计模式只有 23 种,其实不然,除了《设计模式》介绍的 23 种设计模式外,还有很多经典的设计模式,例如我们本文将要介绍的空对象模式。
架构师修炼
2020/07/20
7810
设计模式实战-空对象模式,你肯定不知道,但是项目中会常用到到
【Java8新特性】不了解Optional类,简历上别说你懂Java8!!
作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:
冰河
2020/10/29
6190
【Java8新特性】不了解Optional类,简历上别说你懂Java8!!
Java8之熟透Optional
在写程序的时候一般都遇到过 NullPointerException,所以经常会对程序进行非空的判断:
用户1195962
2019/09/29
5600
推荐阅读
相关推荐
还在用又臭又长的多层 if 判断空值?那我推荐你使用 Optional
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档