java8系列-05 Optional

image

空指針異常我想是程序員見到比較多的異常啦,今天來探索的這個(gè)Optional工具類就是來處理這類問題的。用過Google Guava(后期應(yīng)該會出一個(gè)系列,請持續(xù)關(guān)注)的都應(yīng)該知道,Guava這套工具類庫里面也有一個(gè)Optional,而且作用和今天來探索的這個(gè)java新特性是一樣的。既然又是探索,那我們先打開idea,然后ctrl+鼠標(biāo)左鍵進(jìn)到optional的世界看一下吧。

源碼片段

接下來我將逐行解釋一下源碼(像我這樣給jdk源碼這樣加注釋的怕是很少了_)

// final修飾說明此類是無法被引用的哈
public final class Optional<T> {
    // 這個(gè)是EMPTY的實(shí)例
    private static final Optional<?> EMPTY = new Optional<>();

    // 如果非空,則為該值;如果為空,則表示不存在任何值。
    private final T value;

    // 構(gòu)造私有看來此類也不能被new
    private Optional() {
        this.value = null;
    }

    // 返回一個(gè)空的實(shí)例,@SuppressWarnings不提醒警告
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    // 根據(jù)value來構(gòu)造出一個(gè)實(shí)例
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    // 返回一個(gè)帶有value的optional,注意value如果為空則會報(bào)空指針異常
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // 和上面一樣,但是這里value為空不會有空指針異常
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    // 如果當(dāng)前有值則返回當(dāng)前值,否則拋出NoSuchElementException
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    // 如果這個(gè)Optional是存在的則返回true,否則為false
    public boolean isPresent() {
        return value != null;
    }

    // 如果option對象保存的值不是null,則調(diào)用consumer對象,否則不調(diào)用
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

    // 判斷Optional對象中保存的值是否滿足Predicate,并返回新的Optional。
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    // 如果value不為null,則進(jìn)行函數(shù)運(yùn)算,返回一個(gè)新的Optional,否則返回empty
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }

    // 上一章講到過Stream里面的flatMap,就是對一個(gè)大的集合進(jìn)行一個(gè)扁平化的操作。
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }

    // 不解釋
    public T orElse(T other) {
        return value != null ? value : other;
    }

    // 怎么辦?也不想解釋,關(guān)于Supplier供給者函數(shù)式的作用麻煩翻到此系列的第二章
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    // 重寫了Object的方法
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Optional)) {
            return false;
        }

        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    }

    // 重寫了Object的方法
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    // 如果值不為空則返回Optional[value],否則Optional.empty。認(rèn)真看過我上一章的也許還能記憶起來
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

優(yōu)雅食用

這里撿幾個(gè)比較常用的在這里列出來吧

of && ofNullable

上面注釋有提到,這兩個(gè)都是被用來創(chuàng)建Optional對象。區(qū)別在于ofNullable還判空了。這就造成了ofNullable的實(shí)用性比of要高那么一丟丟。下面來看一個(gè)例子吧~

public class OptionalDemo {
    public static void main(String[] args) {
        Optional<String> ofNullable = Optional.ofNullable(null);
        System.out.println(ofNullable);// Optional.empty

        Optional<String> of = Optional.of(null); // 代碼執(zhí)行到這里會拋出NullPointerException
    }
}

isPresent

isPresent有兩種作用:一個(gè)是判斷是否有值,還有一個(gè)返回的是void,如果不為空的話執(zhí)行Consumer消費(fèi)型函數(shù)式代碼。

public class OptionalDemo {
    public static void main(String[] args) {
        // 先創(chuàng)建一個(gè)Optional
        Optional<String> val = Optional.ofNullable("yes");
        System.out.println(val.isPresent()); // true

        val.ifPresent(s -> System.out.println(s.concat(" or no?"))); // yes or no?
    }
}

filter && map

直接看例子最好啦

public class OptionalDemo {
    public static void main(String[] args) {
        Optional<String> optional = Optional.ofNullable("code666");
        Optional<String> newOptional = optional.map(param->param.concat(".top"));
        System.out.println(newOptional); // Optional[code666.top]

        Optional filterOptional = optional.filter(param->param.contentEquals("Sean")); // 如果條件成立的話會返回Optional[code666]
        System.out.println(filterOptional); // Optional.empty
    }
}

orElse && orElseGet

長得雖然差不多,orElseGet還帶了一個(gè)Supplier供給者函數(shù)看著高大上一點(diǎn),其實(shí)也差不多。記得在第二章有說過,供給者函數(shù)就有點(diǎn)像工廠的味道而已。

public class OptionalDemo {
    public static void main(String[] args) {
        String res = (String) Optional.ofNullable(null).orElse("這個(gè)結(jié)果為空");
        System.out.println(res); // 這個(gè)結(jié)果為空

        String res2 = (String) Optional.ofNullable(null).orElseGet(()-> "The result is empty.");
        System.out.println(res2); // The result is empty.
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容