Java 8中所謂的Optional對象,即一個容器對象,該對象能夠包含一個null或非null值。若是該值不爲null,則調用isPresent()方法將返回true,且調用get()方法會返回該值。java
另外,該對象還有其它方法:app
如可使用orElse()方法給Optional對象設定默認值(當值爲null時,會使用默認值);less
使用ifPresent()方法來執行一段代碼(當值不爲null時,執行代碼段)。ui
Optional主要被用於Java 8的Stream中,簡單舉個例子:this
package optional; import java.util.Optional; import java.util.stream.Stream; public class Snippet { public static void main(String[] args) { Stream<String> names = Stream.of("Lamurudu", "Okanbi", "Oduduwa"); Optional<String> startswl = names.filter(name -> name.startsWith("L")).findFirst(); //判斷是否不爲null if(startswl.isPresent()){ System.out.println(startswl.get()); } //if值爲null:打印「null」;if值不爲null:打印原值 System.out.println(startswl.orElse("null")); //if值不爲null,執行Lambda表達式 startswl.ifPresent(name -> { String s = name.toUpperCase(); System.out.println(s); }); } }
減小NullPointerException異常spa
寫出更加優雅的代碼code
Optional類的屬性和方法以下:對象
咱們一個個看,先看兩個成員屬性;blog
成員屬性ip
以下,一個是EMPTY常量,即存放空值的Optional對象,另外一個是value,即被存放的值,可爲null或非null值;
/** * Common instance for {@code empty()}. */ private static final Optional<?> EMPTY = new Optional<>(); /** * If non-null, the value; if null, indicates no value is present */ private final T value;
構造方法
兩個構造方法,注意都是私有的
一、建立一個包含空值的Optional對象;
二、建立一個非空值的Optional對象;
private Optional() { this.value = null; }
private Optional(T value) { this.value = Objects.requireNonNull(value); }
這個方法很簡單,做用是返回一個Optional實例,裏面存放的value是null,源碼以下:
public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; }
of(T value)方法
很簡單,就是返回一個包含非空值的Optional對象
public static <T> Optional<T> of(T value) { return new Optional<>(value); }
ofNullable(T value)方法
很簡單,返回一個能夠包含空值的Optional對象
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
get()方法
獲得Optional對象裏的值,若是值爲null,則拋出NoSuchElementException異常
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; }
isPresent()方法
很簡單,判斷值是否不爲null
public boolean isPresent() { return value != null; }
ifPresent(Consumer<? super T> consumer)方法
當值不爲null時,執行consumer
public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); }
舉個例子,ifPresent方法執行Lambda表達式,將值轉換爲大寫並打印:
package optional; import java.util.Optional; public class Snippet { public static void main(String[] args) { Optional<String> test = Optional.ofNullable("abcDef"); //值不爲null,執行Lambda表達式, test.ifPresent(name -> { String s = name.toUpperCase(); System.out.println(s); }); //打印ABCDEF } }
filter(Predicate<? super T> predicate)方法
看方法名就知道,該方法是過濾方法,過濾符合條件的Optional對象,這裏的條件用Lambda表達式來定義,
若是入參predicate對象爲null將拋NullPointerException異常,
若是Optional對象的值爲null,將直接返回該Optional對象,
若是Optional對象的值符合限定條件(Lambda表達式來定義),返回該值,不然返回空的Optional對象
源碼以下:
public Optional<T> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : empty(); }
使用示例:
package optional; import java.util.Optional; public class Snippet { public static void main(String[] args) { Optional<String> test = Optional.ofNullable("abcD"); //過濾值的長度小於3的Optional對象 Optional<String> less3 = test.filter((value) -> value.length() < 3); //打印結果 System.out.println(less3.orElse("不符合條件,不打印值!")); } }
map(Function<? super T, ? extends U> mapper)方法
前面的filter方法主要用於過濾,通常不會修改Optional裏面的值,map方法則通常用於修改該值,並返回修改後的Optional對象
若是入參mapper對象爲null將拋NullPointerException異常,
若是Optional對象的值爲null,將直接返回該Optional對象,
最後,執行傳入的lambda表達式,並返回經lambda表達式操做後的Optional對象
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)); } }
使用示例:
package optional; import java.util.Optional; public class Snippet { public static void main(String[] args) { Optional<String> test = Optional.ofNullable("abcD"); //將值修改成大寫 Optional<String> less3 = test.map((value) -> value.toUpperCase()); //打印結果 ABCD System.out.println(less3.orElse("值爲null,不打印!")); } }
flatMap(Function<? super T, Optional<U>> mapper)方法
flatMap方法與map方法基本一致,惟一的區別是,
若是使用flatMap方法,須要本身在Lambda表達式裏將返回值轉換成Optional對象,
而使用map方法則不須要這個步驟,由於map方法的源碼裏已經調用了Optional.ofNullable方法;
源碼:
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)); } }
使用示例:
package optional; import java.util.Optional; public class Snippet { public static void main(String[] args) { Optional<String> test = Optional.ofNullable("abcD"); //使用flatMap,將值修改成大寫 Optional<String> less3 = test.flatMap((value) -> Optional.ofNullable(value.toUpperCase())); //使用map,將值修改成大寫 //Optional<String> less3 = test.map((value) -> value.toUpperCase()); //打印結果 ABCD System.out.println(less3.orElse("值爲null,不打印!")); } }
orElse(T other)方法
很簡單,當值爲null時返回傳入的值,不然返回原值;
源碼:
public T orElse(T other) { return value != null ? value : other; }
orElseGet(Supplier<? extends T> other)方法
功能與orElse(T other)相似,不過該方法可選值的獲取不是經過參數直接獲取,而是經過調用傳入的Lambda表達式獲取
源碼:
public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get(); }
使用示例:
package optional; import java.util.Optional; public class Snippet { public static void main(String[] args) { Optional<String> test = Optional.ofNullable(null); System.out.println(test.orElseGet(() -> "hello")); //將打印hello } }
orElseThrow(Supplier<? extends X> exceptionSupplier)方法
當遇到值爲null時,根據傳入的Lambda表達式跑出指定異常
源碼
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); } }
使用示例:
package optional; import java.util.Optional; public class Snippet { public static void main(String[] args) { Optional<String> test = Optional.ofNullable(null); //這裏的Lambda表達式爲構造方法引用 System.out.println(test.orElseThrow(NullPointerException::new)); //將打印hello } }
jdk1.8.0_31源碼
https://blog.idrsolutions.com/2015/04/java-8-optional-class-explained-in-5-minutes/
https://www.voxxed.com/blog/2015/05/why-even-use-java-8-optional/