聆聽 沉澱 傳播 … 關注微信公衆號【
Java之言
】,助你放棄編程之路!java
系列文章目錄
序號 | 標題 | 文章連接 |
---|---|---|
1 | 玩轉 Java8 Stream,讓你代碼更高效緊湊簡潔 | https://blog.csdn.net/chenlixiao007/article/details/112752413 |
文章目錄
- 系列文章目錄
- 1、Optional 是什麼?
- 2、Optional 有什麼用?
- 3、Optional 源碼詳解
- 4、Optional 類的使用
-
- 4.1 Optional 對象建立
- 4.2 get()
- 4.3 isPresent()
- 4.4 ifPresent(Consumer<? super T> consumer)
- 4.5 filter(Predicate<? super T> predicate)
- 4.6 map(Function<? super T, ? extends U> mapper)
- 4.7 orElse(T other)
- 4.7 orElseGet(Supplier<? extends T> other)
- 4.8 orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
- 4.9 與 Stream 結合使用
1、Optional 是什麼?
官方定義:
public final class Optional<T> extends Object
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
Additional methods that depend on the presence or absence of a contained value are provided, such as orElse() (return a default value if value not present) and ifPresent() (execute a block of code if the value is present).
This is a value-based class; use of identity-sensitivemin operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided.web
Optional
類,一個可包含或不包含非null值
的容器對象
。若是值存在,isPresent()
方法將返回 true 而且get()
返回該值。
這個類還提供了其餘方法,這些方法取決於它所包含值的存在與否,例如orElse()
(若是不存在值,則返回默認值)和ifPresent()
(若是存在值,則執行代碼塊)。
這是一個基於值的類,因此對於Optional實例的一些身份敏感操做(包括引用相等==,hashCode,同步)會產生沒法預料的結果,應該避免使用。編程
2、Optional 有什麼用?
- 既然 Optional 類裏面包含的值能夠爲
null
,不言而喻,那咱們就能夠不用顯式地進行空值檢測,即咱們能夠不用作判空操做,很好的解決了空指針異常問題(NullPointerException
)。- Java8引入了函數式編程,而 Optional 是其中必不可少的一部分,幫助在範式中實現。結合 Stream 能夠寫出簡潔高效的代碼。
先舉個栗子,輸出一個員工的崗位名稱,若是崗位名稱爲空,則輸出默認值 - 實習生:微信
if (null != staff.getPost().getName()) { System.out.println(staff.getPost().getName()); } else { System.out.println("實習生"); }
以上語句有可能拋出NPE,爲了健壯性,咱們須要寫判空:app
if (null != staff) { Post post = staff.getPost(); if (null != post) { String name = post.getName(); if (null != name) { System.out.println(name); } else { System.out.println("實習生"); } } }
可是寫了大量的判空操做,很繁瑣,代碼冗餘還很難維護。若是使用Optional則很簡單以下:ide
System.out.println( Optional.ofNullable(staff).map(Staff::getPost).map(Post::getName).orElse("實習生"));
3、Optional 源碼詳解
public final class Optional<T> { // 包含一個空值的Optional容器對象 private static final Optional<?> EMPTY = new Optional<>(); // Optional容器包含的值 private final T value; // 私有構造方法,建立一個包含空值的Optional容器對象 private Optional() { this.value = null; } // 靜態方法,建立一個空值的Optional容器對象 public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } // 私有構造方法,建立一個包含非空值的Optional容器對象 private Optional(T value) { this.value = Objects.requireNonNull(value); } // 靜態方法,建立一個包含非空值的Optional容器對象 public static <T> Optional<T> of(T value) { return new Optional<>(value); } // 靜態方法,建立一個包含可空值的Optional容器對象 public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } // 獲取值,若是值爲null,則拋出異常 public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; } // 判斷值是否不爲null public boolean isPresent() { return value != null; } // 若是值不爲null,則使用改值調用consumer函數 public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); } // 若是值存志,而且這個值匹配給定的 predicate,返回一個Optional用以描述這個值,不然返回一個空的Optional。 public Optional<T> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : empty(); } // 若是值存在,則對其執行調用映射函數獲得新的返回值。不然返回空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)); } } // 若是值存在,返回基於Optional包含的映射方法的值,不然返回一個空的Optional 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)); } } // 若是值存在,返回此值, 不然返回other。 public T orElse(T other) { return value != null ? value : other; } // 若是值存在,返回此值, 不然調用other函數,並返回other函數的結果。 public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get(); } // 若是值存在,返回此值,不然拋出由Supplier繼承的異常 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); } } }
4、Optional 類的使用
4.1 Optional 對象建立
// 建立一個空值的Optional對象 Optional<Object> emptyOptional = Optional.empty(); // 建立一個值可爲空的Optional對象 Optional<Staff> staffOptional = Optional.ofNullable(staff); // 建立一個非空值的Optional對象 Optional<Staff> staffOptional1 = Optional.of(staff);
4.2 get()
// 返回Optional容器對象中包含的值,若是值爲null則拋出異常 Staff staff = staffOptional.get();
4.3 isPresent()
// 判斷值是否存在 if (staffOptional.isPresent()) { Staff staff = staffOptional.get(); }
4.4 ifPresent(Consumer<? super T> consumer)
// 若是值存在,則輸出值 staffOptional.ifPresent(System.out::println);
4.5 filter(Predicate<? super T> predicate)
// 是否存在18歲的員工,若是存在,則輸出她的姓名 staffOptional.filter(staff -> staff.getAge() == 18) .ifPresent(staff -> System.out.println(staff.getName()));
4.6 map(Function<? super T, ? extends U> mapper)
// 獲取員工的姓名,若是staff或name爲null,輸出'未知' System.out.println(staffOptional.map(Staff::getName).orElse("未知"));
4.7 orElse(T other)
// 若是staff爲null,將新生成的Staff對象賦值給staff staff = Optional.ofNullable(staff).orElse(new Staff());
4.7 orElseGet(Supplier<? extends T> other)
// // 若是staff爲null,才new出一個Staff對象,賦值給staff,它與orElse不一樣的是執行時機不一樣,orElseGet是值爲空才調用other函數。 staff = Optional.ofNullable(staff).orElseGet(Staff::new);
4.8 orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
// 若是staff爲null,則拋出異常 staff = Optional.ofNullable(staff).orElseThrow(() -> new NullPointerException());
4.9 與 Stream 結合使用
// 找出一個員工大於等於18歲的員工 Optional<Staff> staffOptional = staffList.stream().filter(staff -> staff.getAge() >= 18).findFirst(); if (staffOptional.isPresent()) { Staff staff = staffOptional2.get(); }
本文同步分享在 博客「Μr.ηobοdy」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。svg