欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: ostatsu

如何防范 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。