溫故而知新:Java 8 之 Optional

Java 11 已經發布好久了,而不少企業還在用很老的 Java 版本,這年頭,再保守的企業也應該用上 Java 8 了。咱們不妨回顧一下 Java 8 的新(現已經是老)特性。html

主要 API

java.util.Optional 的那些方法(method)卻是沒啥可講的,看看文檔就好了。這裏簡要列舉一下:java

構造:app

static <T> Optional<T> empty()
static <T> Optional<T> of(T value)
static <T> Optional<T> ofNullable(T value)

Optional 的構造方法都是私有的,提供 3 個靜態方法來生成 Optional 對象。其中,empty 構造一個內部不含值的 Optional 對象,of 不接受 nullofNullable 能夠接受 null函數

其餘方法:調試

T get()
boolean isPresent()
void ifPresent(Consumer<? super T> consumer)
Optional<T> filter(Predicate<? super T> predicate)
<U> Optional<U> map(Function<? super T, ? extends U> mapper)
<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
T orElse(T other)
T orElseGet(Supplier<? extends T> other)
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

做用分別以下:code

T get()

獲取裏面的值,若不存在,引起 NoSuchElementExceptionhtm

boolean isPresent()

檢查裏面是否有值。對象

void ifPresent(Consumer<? super T> consumer)

若是裏面有值,則對那個值作一些處理(消費它)。文檔

Optional<T> filter(Predicate<? super T> predicate)

用條件 predicate 進行過濾,條件知足則返回自己,不然返回一個不含值的 Optional<T>get

<U> Optional<U> map(Function<? super T, ? extends U> mapper)
<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

兩者大同小異,都是對裏面的值進行某種操做,不一樣的是,flatMap 要求返回值是 Optional<U>

T orElse(T other)
T orElseGet(Supplier<? extends T> other)
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

這三個方法都是獲取值,不一樣點在於無值時三者的行爲:orElse 提供一個默認值 otherorElseGet 提供由一個函數返回的值,orElseThrow 引起一個異常。

正着

咱們最容易想到的用法固然是 isPresent

Optional<String> os = Optional.ofNullable(s);
if (os.isPresent()) {
    // 一些代碼
}

但這麼作沒啥意義,還不如與 null 做比較直觀。

Optional 也不該出如今函數的參數上,由於調用者不應有這樣的心智負擔。

就像這篇文章

http://www.importnew.com/22060.html

所言,咱們須要的是除了 isPresentget 以外的其餘方法。

例如,咱們在程序中要讀取 FLUTE_DEBUG 環境變量,若是它存在,且在不區分大小寫的狀況下屬於 "true""on""1",則認爲程序處於調試模式下,不然認爲處於生產模式下。

public static boolean inDebugMode() {
    return Optional.ofNullable(System.getenv("FLUTE_DEBUG"))
            .map(String::toLowerCase)
            .map(s -> "true".equals(s) || "on".equals(s) || "1".equals(s))
            .orElse(false);
}

再例如,用來實現函數的默認參數:

class MqttClientConfig {
    // 各個屬性省略
}

class MqttClient {
    private MqttClient() {
    }

    private static MqttClientConfig getDefaultConfig() {
        // 將全部的屬性設爲默認
        // 此處從略
        return new MqttClientConfig();
    }

    public static MqttClient create(MqttClientConfig config) {
        // 若是 config 爲 null
        // 則一切按照默認
        MqttClientConfig theConfig = Optional.ofNullable(config).orElseGet(MqttClient::getDefaultConfig);

        // ......
    }
}

上面的代碼示意了一個 MQTT 客戶端建立的過程。固然,只有一個參數的方法,用這樣的方式不如加一個重載,當參數多的時候,Optional 的便利才得以體現。

相關文章
相關標籤/搜索