Java9 Optional類

在這篇文章中,我們將討論「Java SE 8的Optional類如何解決空檢查問題?」以及「Java SE 9的Optional類改進」。

作爲Java開發人員,我們知道爲了避免NullPointerException錯誤而對每個對象進行空檢查時需要做不少的工作。

Java SE 8:Optional類基礎

Oracle公司已經引入了Optional類作爲java.util包的一部分。 它是一個容器對象,它可能包含或不包含非空值。

它主要用於避免大量空檢查和NullPointerException問題。 儘管它是java.util包的一部分,但它並未實現任何Collection API接口。 它擴展了Object類,如下所示。

public final class Optional<T> extends Object

它是final類,因此不能重寫它。 如果可選對象不爲空,則表示該對象中存在值。 如果它是空的,則不存在如下所示的值。

Java9 Optional類

Java SE 8:Optional基本示例

在本節中,我們將探討如何使用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:Optional類改進

在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對象的一個OptionalStream轉換爲一個Employee流,以便可以在結果代碼中懶地處理這個結果。

Java SE 8樣式:Optional方法

在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/[email protected]


jshell> opStr.or(supStr)
$5 ==> Optional[Rams]