Optional方法解釋以及使用


Optional類的方法

方法 描述
empty 返回一個空的Optional類實例
of 將對象封裝到Optional類中去,要求對象不能夠為空,否則返回一個NullPointerException
ofNullable 獲取得到Optional類封裝的對象,如果對象為空,那么返回一個空實例,如果不為空,返回一個封裝了對象的Optional實例
filter 如果值存在而且能夠滿足提供的謂詞,就返回包含該值的Optional對象,否則返回一個空的Optional類實例
map 如果Optional類封裝的值存在,那么執行map函數中定義的內容
flatMap 如果該值存在,通過Function函數,返回一個Optional類型的值,否則返回一個空的Optional類實例
get 如果值存在,那么將Optional類實例封裝的值返回,否則將會拋出NoSuchElementException異常
isPresent 如果存在封裝的對象,那么返回true;如果不存在,那么返回false
ifPresent 如果存在封裝的對象,那么執行后面的消費方法;如果不存在,那么不做任何事情
orElse 如果Optional實例對象是empty,那么使用默認的值來代替
orElseGet 如果有值,則獲取得到將其返回;如果沒有值,那么將會使用指定的函數生成的值
orElseThrow 如果有值將其進行返回,否則拋出一個指定的異常

之前寫過一篇Optional類的說明,但是感覺不同情況下有不同的用法,所以現在結合源碼再將使用場景結合一下使用。

Optional類和泛型T是相互結合着的,表示的是Option這個箱子里面裝的是T類型的value,但是這個value有可能是null,也有可能不為null

/***
可能包含也可能不包含非空值的容器對象。 
如果存在值,isPresent() 將返回 true,get() 將返回該值。
提供了依賴於包含值的存在與否的其他方法,例如 orElse()(如果值不存在則返回默認值)和 ifPresent()(如果值存在則執行代碼塊)。
這是一個基於值的類; 在 Optional 實例上使用身份敏感操作(包括引用相等 (==)、身份哈希碼或同步)可能會產生不可預測的結果,應該避免。

所以可以將這個類的實例理解成是一個對值做處理的容器
*/
public final class Optional<T> {
	// Optiaonal箱子里面裝的值是T類型的為null的值
    private static final Optional<?> EMPTY = new Optional<>();

	// Optional這個箱子裝的值
    private final T value;

	// value為null
    private Optional() {
        this.value = null;
    }

	// 返回的是T類型的null。相當於是User user = null
    // 只不過這里使用Optional類給包裝着
    public static<T> Optional<T> empty() {
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

	// 如果傳遞過來的value是null,那么將會存在NPE
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

	// 傳入進來的value如果是null,那么將會存在NPE
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

	// 如果value為null,那么返回Optional<null>;如果存在着值,那么返回Optional<value>
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

	// 如果值為null,那么就直接拋出異常;如果不為null,就直接返回這個value。
    // 這里說明了這里還是有可能存在着為null的可能性的
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

	// 如果value不是null,那么就直接返回true;如果value是null,那么就直接返回false;
    public boolean isPresent() {
        return value != null;
    }

    // 如果value不為null,那么就可以對這個value值來進行操作了
    // 如果為null,那么就什么都不做
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

	// 過濾方法。看看如何來進行實現的。
    // 首先判斷predicate對象不能夠是空的,如果是空的就直接拋出空指針異常
    // 然后在判斷這個是否有,可以看到,如果value為null,那么直接返回這個value為空的對象
    // 如果value不為null的時候,然后進行下一步操作。如果value符合自定義的predicate,那么就直接返回這個value的實例對象;不然就返回的是value=null的實例     // 對象
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    // 如果說這樣的對象不為null,那么就執行下面的步驟
    // 如果當前對象的value為null,那么將會返回value為null的實例對象;如果不為null,那么就會按照mapper中的方法將值來進行轉換。
    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));
        }
    }


    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));
        }
    }

    // 這個比較簡單了。自定義實現。如果value是空,那么就根據傳進來的值作為value
    public T orElse(T other) {
        return value != null ? value : other;
    }

	// 這個也是比較容易來理解的。如果value不為null,那么就直接返回;如果value為null,那么就自己來定義一個值賦值給value
    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();
        }
    }

    /**
     * Indicates whether some other object is "equal to" this Optional. The
     * other object is considered equal if:
     * <ul>
     * <li>it is also an {@code Optional} and;
     * <li>both instances have no value present or;
     * <li>the present values are "equal to" each other via {@code equals()}.
     * </ul>
     *
     * @param obj an object to be tested for equality
     * @return {code true} if the other object is "equal to" this object
     * otherwise {@code false}
     */
    @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);
    }

    /**
     * Returns the hash code value of the present value, if any, or 0 (zero) if
     * no value is present.
     *
     * @return hash code value of the present value or 0 if no value is present
     */
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    /**
     * Returns a non-empty string representation of this Optional suitable for
     * debugging. The exact presentation format is unspecified and may vary
     * between implementations and versions.
     *
     * @implSpec If a value is present the result must include its string
     * representation in the result. Empty and present Optionals must be
     * unambiguously differentiable.
     *
     * @return the string representation of this instance
     */
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

對上面的方法做了一個總結:可以發現上面的方法總體來說都是:對值是否是null來做了處理,防止出現空指針異常

如果是null的話,可以實現怎樣的操作;如果不是null的話,又可以做怎樣的操作;以及對值可能為null的處理方式

構造方法中可以看到構造都被私有化了,只有本類中的其他的非private修飾的才能夠來創建實例化對象。

對於空參構造來說,創造出來的對象的value屬性為null;對於有參構造來說,value值不為null;

所以總結來說,是創建出來的對象不為null,value值可能是null,也可以不是null;具體的得看是哪個方法來進行調用的。

對於這個Optional類來說,加載類的時候就已經有了一個默認的EMPTY對象,value是為null的。

然后再來一個比較常用的:

       Optional<User> optional = userRepository.selectOne(entity);
	  // 如果optional不為null,那么返回ok;否則返回后面的錯誤碼。
       return optional.map(ResponseResult::getOk).orElseGet(() -> ResponseResult.getError("賬號/密碼錯誤"));

還有一個對參數校驗的

        String str = null;
        Optional.ofNullable(str).orElseThrow(()-> new RuntimeException("str為空"));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM