空检查vs可选存在检查
有人可以解释Optional
如何帮助我们避免NullPointerException
?空检查vs可选存在检查
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
提供以外的事实,它可以帮助我们知道一个函数是否真的有返回值的
比方说,你想要获取函数返回的字符串,将其转换为大写,然后将其打印出来。如果您有:
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
代替。所以,如果你在Optional
上盲目地调用get
,它确实与在引用上调用方法而不检查其是否为空几乎是相同的。
(出于这个原因,Brian Goetz认为Optional.get
是用Java 8中最大的错误见他与安格兰格JAX 2015 Fragen und Antworten zu Java 8接受采访时约16分钟。我不知道这是最大的,但它是一个错误。人们只是不要指望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);
哇,我永远不会注意到像ifPresent这些额外的功能,谢谢。 – LegendLength
的可能的复制[用于可选用途]的(http://*.com/questions/23454952/uses-for-optional) –
可能的复制[可选与空。在Java 8中可选的目的是什么?](http://*.com/questions/28746482/optional-vs-null-what-is-the-purpose-of-optional-in-java-8) – Mritunjay
那么,一方面,你可以在不存在的'Optional'上使用'x.toString()',但是你不能在'null'上使用它。还有一些像'x.equals(y)'。 – ajb