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類,因此不能重寫它。 如果可選物件不為空,則表示該物件中存在值。 如果它是空的,則不存在如下所示的值。

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]