Null check vs Optional是检查

时间:2016-11-24 04:48:46

标签: java functional-programming java-8 optional

有人可以解释Optional如何帮助我们避免NullPointerException

Optional<String> op = someFunc()
if(op.isPresent()) {
   op.get();
}
String possibleNull = op.get();

这段代码也不容易出现NullPointerException吗?如果是这样,那么为什么这个代码优先于

String op = someFunc()
if(op != null) {
   op.get();
}
String possibleNull = op;

Optional提供了哪些可能的好处,除了它有助于我们知道函数是否实际具有返回值

1 个答案:

答案 0 :(得分:24)

假设你想获得一个函数返回的字符串,将其转换为大写,然后将其打印出来。如果你有:

String someFunc() { ... }

你可能想写:

System.out.println(someFunc().toUpperCase());

当然,如果NullPointerException返回someFunc,则会抛出null。相反,假设我们有这个:

Optional<String> someFunc() { ... }

然后

System.out.println(someFunc().toUpperCase());
由于Optional没有toUpperCase方法,

无法工作。在这一点上 - 希望 - 你会遇到一个Optional,这会让你想到Optional空洞的情况。这有助于避免NPE,但可能只是在某种程度上。

现在你可能会专注于如何从Optional中获取价值,而你可能会忘记空案例。啊,有get方法:

System.out.println(someFunc().get().toUpperCase());

这会带来与NPE相同的问题,但异常是NoSuchElementException。因此,如果你盲目地在get上调用Optional,那么就像在引用上调用方法而不检查它是否为空而实际上是一样的。

(出于这个原因,Brian Goetz认为Optional.get是Java 8中最大的错误。在约16分钟的时间内,他会看到Angelika Langer JAX 2015 Fragen und Antworten zu Java 8的采访。我在这里不确定它是最大的,但这是一个错误。人们不希望get抛出异常。)

如果您非常勤于检查空引用或空选项,那么

Optional<String> os = someFunc();
if (os.isPresent()) {
    System.out.println(os.get().toUpperCase());
}

几乎没有比旧的

更好
String s = someFunc();
if (s != null) {
    System.out.println(s.toUpperCase());
}

Optional真正的优势在于它是一个具有相当丰富的API的库类,可以安全地处理空案例。通过将一些方法调用链接到首先返回Optional的方法,通常可以处理Optional中可能包含的值。例如,我们可以按如下方式重写上面的示例:

someFunc().map(String::toUpperCase)
          .ifPresent(System.out::println);