1. 程式人生 > 其它 >Java 8 Optional正確使用姿勢

Java 8 Optional正確使用姿勢

在Java程式中,空指標異常(NullPointerException)可以說是最常見的的了,所以我們在打程式碼的時候會到處使用if(null == A){ ...... }這類操作。Java 8提供了Optional型別來一定程度上緩解NPE問題,這裡主要因為自己在使用Optional型別時候踩到一些坑,故作此總結加深印象。

Optional是什麼

Optional是什麼?有什麼作用?什麼時候該用?什麼時候最好不用?這裡我也不去網上搜索搬定義了,直接讀原始碼類上的註釋說明就可以明白了

package java.util;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**    ----Optional是什麼----
 * A container object which may or may not contain a non-{@code null} value.
 * If a value is present, {@code isPresent()} returns {@code true}. If no
 * value is present, the object is considered <i>empty</i> and
 * {@code isPresent()} returns {@code false}.
 *    ----Optional的附加方法說明----
 * <p>Additional methods that depend on the presence or absence of a contained
 * value are provided, such as {@link #orElse(Object) orElse()}
 * (returns a default value if no value is present) and
 * {@link #ifPresent(Consumer) ifPresent()} (performs an
 * action if a value is present).
 *    ----什麼時候不該用Optional----
 * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
 * class; use of identity-sensitive operations (including reference equality
 * ({@code ==}), identity hash code, or synchronization) on instances of
 * {@code Optional} may have unpredictable results and should be avoided.
 *    ----什麼時候用Optional----
 * @apiNote
 * {@code Optional} is primarily intended for use as a method return type where
 * there is a clear need to represent "no result," and where using {@code null}
 * is likely to cause errors. A variable whose type is {@code Optional} should
 * never itself be {@code null}; it should always point to an {@code Optional}
 * instance.
 *
 * @param <T> the type of value
 * @since 1.8
 */

正確使用姿勢

1 使用Optional 的目的主要是為了清晰地表達返回值中沒有結果的可能性

所以一般只用來作為方法的返回值型別,例如:

Optional 是不可變型別,是加了final修飾的類,並且,它是沒用共有構造器的,所以我們沒辦法new出一個Optional 來,我們只能使用它所提供的三個方法來得到Optional 物件:

// 1 
public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

// 2 
public static <T> Optional<T> of(T value) {
        return new Optional<>(Objects.requireNonNull(value));
    }
// 3 
public static <T> Optional<T> ofNullable(T value) {
        return value == null ? (Optional<T>) EMPTY
                             : new Optional<>(value);
    }

下面是個人對Optional 使用的一些總結:

2 不要直接給Optional 賦null值

3 如果不能保證物件一定不為null,那就用Optional .ofNullable(),因為Optional .of()會拋NPE

    /**
     * Returns an {@code Optional} describing the given non-{@code null}
     * value.
     *
     * @param value the value to describe, which must be non-{@code null}
     * @param <T> the type of the value
     * @return an {@code Optional} with the value present
     * @throws NullPointerException if value is {@code null} //這裡明確了value為空會NPE!!!
     */
    public static <T> Optional<T> of(T value) {
        return new Optional<>(Objects.requireNonNull(value));
    }

    /**
     * Returns an {@code Optional} describing the given value, if
     * non-{@code null}, otherwise returns an empty {@code Optional}.
     *
     * @param value the possibly-{@code null} value to describe
     * @param <T> the type of the value
     * @return an {@code Optional} with a present value if the specified value
     *         is non-{@code null}, otherwise an empty {@code Optional}
     */
    @SuppressWarnings("unchecked")
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? (Optional<T>) EMPTY
                             : new Optional<>(value);
    }

4 使用isEmpty()或isPresent()來作為判斷value是否為空,而不是if(optional1 == null) {...}

5 使用orElse, orElseGet, orElseThrow這幾個API來避免自己寫if else語句

6 使用equals方法判斷Optional物件是否相等,而不是使用“==”

因為Optional類已經覆蓋了equals方法,所以想必你已經能猜到上面的輸出結果了吧

7 使用filter對value物件做業務邏輯判斷

首先我們在Shop類中加個如下簡單的業務邏輯判斷方法,然後再進行測試看看結果:

    //在Shop類中加個簡單的業務邏輯判斷方法
    public Boolean isRecommanded(){
        if (Objects.equals(this.shopId,1L)){
            return true;
        }
        return false;
    }

如果提供給filter中的返回false,那麼就會得到一個空的Optional,而這時再呼叫get方法就會報如上錯誤,所以在使用Optional的get方法前一定要使用isPresent()方法先判斷!

以上就是個人對Optional學習和使用的一些總結,以此文記錄一番