• 在 Java 8 中避免 Null 检查


    如何预防 Java 中著名的 NullPointerException 异常?这是每个 Java 初学者迟早会问到的关键问题之一。而且中级和高级程序员也在时时刻刻规避这个错误。其是迄今为止 Java 以及很多其他编程语言中最流行的一种错误。

    Null 引用的发明者 Tony Hoare 在 2009 年道歉,并称这种错误为他的十亿美元错误。

    我将其称之为自己的十亿美元错误。它的发明是在1965 年,那时我用一个面向对象语言(ALGOL W)设计了第一个全面的引用类型系统。我的目的是确保所有引用的使用都是绝对安全的,编译器会自动进行检查。但是我未能抵御住诱惑,加入了 Null 引用,仅仅是因为实现起来非常容易。它导致了数不清的错误、漏洞和系统崩溃,可能在之后 40 年中造成了十亿美元的损失。

    无论如何,我们必须要面对它。所以,我们到底能做些什么来防止 NullPointerException 异常呢?那么,答案显然是对其添加 null 检查。由于 null 检查还是挺麻烦和痛苦的,很多语言为了处理 null 检查添加了特殊的语法,即空合并运算符 —— 其在像 Groovy 或 Kotlin 这样的语言中也被称为 Elvis 运算符。

    不幸的是 Java 没有提供这样的语法糖。但幸运的是这在 Java 8 中得到了改善。这篇文章介绍了如何利用像 lambda 表达式这样的 Java 8 新特性来防止编写不必要的 null 检查的几个技巧。

     

    在 Java 8 中提高 Null 的安全性

     

    我已经在另一篇文章中说明了我们可以如何利用 Java 8 的 Optional 类型来预防 null 检查。下面是那篇文章中的示例代码。

    假设我们有一个像这样的类层次结构:

    class Outer {
        Nested nested;
        Nested getNested() {
            return nested;
        }
    }class Nested {
        Inner inner;
        Inner getInner() {
            return inner;
        }
    }class Inner {
        String foo;
        String getFoo() {
            return foo;
        }
    }
    

      

    解决这种结构的深层嵌套路径是有点麻烦的。我们必须编写一堆 null 检查来确保不会导致一个 NullPointerException:

    Outer outer = new Outer();if (outer != null && outer.nested != null && outer.nested.inner != null) {
        System.out.println(outer.nested.inner.foo);
    }
    

      

    我们可以通过利用 Java 8 的 Optional 类型来摆脱所有这些 null 检查。map 方法接收一个 Function 类型的 lambda 表达式,并自动将每个 function 的结果包装成一个 Optional 对象。这使我们能够在一行中进行多个 map 操作。Null 检查是在底层自动处理的。

    Optional.of(new Outer())
        .map(Outer::getNested)    .map(Nested::getInner)    .map(Inner::getFoo)    .ifPresent(System.out::println);
    

      

    还有一种实现相同作用的方式就是通过利用一个 supplier 函数来解决嵌套路径的问题:

    Outer obj = new Outer();
    resolve(() -> obj.getNested().getInner().getFoo());
        .ifPresent(System.out::println);
    

      

    调用 obj.getNested().getInner().getFoo()) 可能会抛出一个 NullPointerException 异常。在这种情况下,该异常将会被捕获,而该方法会返回 Optional.empty()。

    public static <T> Optional<T> resolve(Supplier<T> resolver) {
        try {
            T result = resolver.get();
            return Optional.ofNullable(result);
        }
        catch (NullPointerException e) {
            return Optional.empty();
        }
    }
    

      

    请记住,这两个解决方案可能没有传统 null 检查那么高的性能。不过在大多数情况下不会有太大问题。

    像往常一样,上面的示例代码都托管在 GitHub。

    祝编码愉快!

    原文:https://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/

    译文:https://www.oschina.net/translate/avoid-null-checks-in-java

    原文作者:Benjamin

    译文作者:ostatsu

    更多精彩内容也可查看 https://xdclass.net/#/index

  • 相关阅读:
    TCP/IP,HTTP,HTTPS,WEBSocket协议
    mysql优化
    PHP基础算法
    php----函数大全
    面试题总结101-)
    扫描一个目录下的所有文件,根据这些文件的创建日期生成一个文件夹,然后把这些文件移入这个文件夹下面
    对执行文件下的文件按照时间
    [合集]解决Python报错:local variable 'xxx' referenced before assignment
    python 函数私有方法
    去哪儿面试题- 一组描述由人组成的网络的测试用例校验是否联通
  • 原文地址:https://www.cnblogs.com/xdclass/p/9753113.html
Copyright © 2020-2023  润新知