Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 362|回复: 0

Java8 新特性

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-8 04:50:47 | 显示全部楼层 |阅读模式

    文章整理翻译自 https://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/

    文章首发于个人网站: https://www.exception.site/java8/java8-avoid-null-check

    要说 Java 编程中哪个异常是你印象最深刻的,那 NullPointerException 空指针可以说是臭名昭著的。不要说初级程序员会碰到,
    即使是中级,专家级程序员稍不留神,就会掉入这个坑里。

    Null 引用的发明者 Tony Hoare 曾在 2009 年作出道歉声明,声明中表示,到目前为止,空指针异常大约给企业已造成数十亿美元的损失。

    下面是 Tony Hoare 的原话:

    我将 Null 引用的设计称为是一个数十亿美元的错误。1965 那年,我正在用面向对象语言(ALGOL W) 设计首个功能全面的系统。当时我的考量是,确保所有被使用的引用都是安全的,编译器会自动进行检查。但是,我没有抵住诱惑,加入了 Null 引用,仅仅是为了实现起来省事。这之后,它导致了数不清的 bug、错误和系统崩溃,也为企业导致了不可估量的损失。

    事已至此,我们必须学会面对它。So, 我们要如何防止空指针异常呢?

    唯一的办法就是对可能为 Null 的对象添加检查。但是 Null 检查是繁琐且痛苦的。所以一些比较新的语言为了处理 Null 检查,特意添加了特殊的语法,如空合并运算符

    GroovyKotlin 这样的语言中也被称为 Elvis 运算符。

    不幸的是,在老版本的 Java 中并没有提供这样的语法糖。Java8 中在这方面做了改进。所以,这篇文章就特意来介绍一下如何在 Java8 中利用新特性来编写防止 NullPointerException的发生。

    Java8 中如何加强对 Null 对象的检查?

    在上篇文章 Java8 新特性指导手册 中简单的提了一下如何通过 Optional 类来对对象做空校验。接下来,我们再细说一下:

    在业务系统中,对象中嵌套对象是经常发生的场景,如下示例代码:

    // 最外层对象
    class Outer {
        Nested nested;
        Nested getNested() {
            return nested;
        }
    }
    // 第二层对象
    class Nested {
        Inner inner;
        Inner getInner() {
            return inner;
        }
    }
    // 最底层对象
    class Inner {
        String foo;
        String getFoo() {
            return foo;
        }
    }
    

    业务中,假设我们需要获取 Outer 对象对底层的 Inner 中的 foo 属性,我们必须写一堆的非空校验,来防止发生 NullPointerException

    // 繁琐的代码
    Outer outer = new Outer();
    if (outer != null && outer.nested != null && outer.nested.inner != null) {
        System.out.println(outer.nested.inner.foo);
    }
    

    通过 Optional

    在 Java8 中,我们有更优雅的解决方式,那就是使用 Optional是说,我们可以在一行代码中,进行流水式的 map 操作。而 map 方法内部会自动进行空校验

    Optional.of(new Outer())
        .map(Outer::getNested)
        .map(Nested::getInner)
        .map(Inner::getFoo
        .ifPresent(System.out::println); // 如果不为空,最终输出 foo 的值
    

    通过 suppiler 函数自定义增强 API

    上面这种方式个人感觉还是有点啰嗦,我们可以利用 suppiler 函数来出一个终极解决方案:

    public static <T> Optional<T> resolve(Supplier<T> resolver) {
        try {
            T result = resolver.get();
            return Optional.ofNullable(result);
        }
        catch (NullPointerException e) {
            // 可能会抛出空指针异常,直接返回一个空的 Optional 对象
            return Optional.empty();
        }
    }
    

    利用上面的 resolve 方法来重构上述的非空校验代码段:

    Outer obj = new Outer();
    // 直接调用 resolve 方法,内部做空指针的处理
    resolve(() -> obj.getNested().getInner().getFoo());
        .ifPresent(System.out::println); // 如果不为空,最终输出 foo 的值
    

    最后

    你需要知道的是,上面这两个解决方案并没传统的 null 检查性能那么高效。但在绝大部分业务场景下,舍弃那么一丢丢的性能来方便编码,是完全可取,
    除非是那种对性能有严格要求的场景,我们才不建议使用。

    个人觉得,真要拿这点性能说事,还不如去优化优化 sql 语句,业务逻辑等。

    GitHub 地址

    https://github.com/weiwosuoai/java8_guide

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-3 22:09 , Processed in 0.054128 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表