Java 8 Optional正確使用姿勢
阿新 • • 發佈:2021-07-17
在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學習和使用的一些總結,以此文記錄一番