在這篇文章中,我們將討論「Java SE 8的Optional
類如何解決空檢查問題?」以及「Java SE 9的Optional
類改進」。
作為Java開發人員,我們知道為了避免NullPointerException
錯誤而對每個物件進行空檢查時需要做不少的工作。
Oracle公司已經引入了Optional
類作為java.util
包的一部分。 它是一個容器物件,它可能包含或不包含非空值。
它主要用於避免大量空檢查和NullPointerException
問題。 儘管它是java.util
包的一部分,但它並未實現任何Collection
API介面。 它擴充套件了Object
類,如下所示。
public final class Optional<T> extends Object
它是final
類,因此不能重寫它。 如果可選物件不為空,則表示該物件中存在值。 如果它是空的,則不存在如下所示的值。
在本節中,我們將探討如何使用Java SE 8 Optional
物件來避免空檢查和NullPointerException
。
它是Optional
類中的簡單基本範例。 它演示了如何使用Optional.empty()
建立一個空的Optional
物件,以及如何建立非空的Optional
物件。
import java.util.Optional;
public class JavaSE8OptionalDemo
{
public static void main(String[] args)
{
System.out.println(division(4,2));
System.out.println(division(4,0));
}
public static Optional<Integer> division(Integer i1,Integer i2)
{
if(i2 == 0) return Optional.empty();
else {
Integer i3 = i1/i2;
return Optional.of(i3);
}
}
}
執行上面範例程式碼,得到以下結果 -
Optional[2]
Optional.empty
在Java SE 9中,Oracle公司引入了以下三種方法來改進Optional
類功能。幾個方法如下所示 -
stream()
ifPresentOrElse()
or()
我們將逐一介紹這些方法,並在接下來的章節中詳細討論一些合適的例子。
Java SE 9:Optional類的stream()方法
如果給定Optional
物件中存在一個值,則此stream()
方法將返回具有該值的順序流。 否則,它將返回一個空流。
Java 9已經新增了stream()
方法來延遲處理Optional
物件,如下所示:
Stream<Optional> emp = getEmployee(id)
Stream empStream = emp.flatMap(Optional::stream)
這裡使用Optional.stream()
方法將Employee
物件的一個Optional
的Stream
轉換為一個Employee
流,以便可以在結果程式碼中懶地處理這個結果。
在Java SE 8中,我們應該使用ifPresent()
,isPresent()
和orElse()
等方法來檢查Optional
物件並對其執行一些功能。 執行此操作有點繁瑣。 但是,Java SE 9引入了一種新方法來解決這個問題。
在這裡,我們將探索以下三種可選的類方法:
ifPresent()
- 如果存在值,則使用該值執行給定操作,否則不執行任何操作。
void ifPresent(Consumer action)
isPresent()
- 如果存在值,則返回true,否則返回false。
boolean isPresent()
orElse()
- 如果存在值,則返回該值,否則返回其他值。
public T orElse(T other)
範例程式碼 -
import java.util.Optional;
public class JavaSE8OptionalDemo
{
public static void main(String[] args)
{
Optional<Integer> opt1 = division(4,2);
opt1.ifPresent( x -> System.out.println("Option1: Result found = " + x));
Optional<Integer> opt2 = division(4,0);
opt2.ifPresent( x -> System.out.println("Option2: Result found: " + x));
System.out.println("Option2: Result not found, default vlaue = " + opt2.orElse(new Integer(0)));
if(opt2.isPresent())
System.out.println("Option2: Result found.");
else
System.out.println("Option2: Result not found.");
}
public static Optional<Integer> division(Integer i1,Integer i2)
{
if(i2 == 0) return Optional.empty();
else {
Integer i3 = i1/i2;
return Optional.of(i3);
}
}
}
執行上面範例程式碼,得到以下結果 -
Option1: Result found = 2
Option2: Result not found, default vlaue = 0
Option2: Result not found.
Java SE 9:可選ifPresentOrElse()方法
在本節中,通過使用Java SE 9的Optional
類的ifPresentOrElse()
方法來探索相同型別的場景。 它以一種很好的方式將ifPresent()
,isPresent()
和orElse()
方法等所有方法組合在一起。
Java SE 9 Optional
類 ifPresentOrElse()API: -
public void ifPresentOrElse(Consumerl<? super Tl> action, Runnable emptyAction)
如果存在值,則使用該值執行給定操作,否則執行給定的基於空的操作。
ifPresentOrElse()範例
jshell> Optional<Integer> opt1 = Optional.of(4)
opt1 ==> Optional[4]
jshell> opt1.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Result found: 4
jshell> Optional<Integer> opt2 = Optional.empty()
opt2 ==> Optional.empty
jshell> opt2.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Not Found.
Java SE 9: Optional類or()方法
在Java SE 9Optional類API中,如果Optional
包含值,則使用or()
方法返回值。 否則返回供應商中指定的值。 這個or()
方法將供應商作為引數來指定預設值。
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
讓我們看一個範例,首先在Optional
中顯示一個值。
Java SE 9 Optional類of()方法
jshell> Optional<String> opStr = Optional.of("Rams")
opStr ==> Optional[Rams]
jshell> import java.util.function.*
jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2
jshell> opStr.or(supStr)
$5 ==> Optional[Rams]