有人可以解释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
提供了哪些可能的好处,除了它有助于我们知道函数是否实际具有返回值
答案 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);