2016-11-24 92 views
3

有人可以解釋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提供以外的事實,它可以幫助我們知道一個函數是否真的有返回值的

+0

的可能的複製[用於可選用途]的(http://stackoverflow.com/questions/23454952/uses-for-optional) –

+1

可能的複製[可選與空。在Java 8中可選的目的是什麼?](http://stackoverflow.com/questions/28746482/optional-vs-null-what-is-the-purpose-of-optional-in-java-8) – Mritunjay

+0

那麼,一方面,你可以在不存在的'Optional'上使用'x.toString()',但是你不能在'null'上使用它。還有一些像'x.equals(y)'。 – ajb

回答

13

比方說,你想要獲取函數返回的字符串,將其轉換爲大寫,然後將其打印出來。如果您有:

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); 
+0

哇,我永遠不會注意到像ifPresent這些額外的功能,謝謝。 – LegendLength