Java8判空新寫法

一、前言

? ? 空指針真的是我們開發中經常會碰到的問題,例如一個類

public class User() {
? ? private String userName;
? ? private String password;
? ? private List<User> children;
}

? ? 代碼中如下調用:user.getChildren().getUserName()
? ? 當user為空的時候,這句代碼就有可能會報NullPointerException。為了解決這類問題呢,我們通常就會做很多的判空操作

if(user!=null) {
?????User smallUser = user.getChildren();
?????if(smallUser!=null){
?????????String smallName = smallUser.getUserName();
?????}
}

? ? 這種方式是最不優雅的,為了避免這類問題,Java8提供了Optional類來優化這種寫法。Optional不是對null關鍵字的一種替代,而是對于null判定提供了一種更加優雅的實現。

二、API介紹

? ??1、of(T value),ofNullable(T value)
? ??????Optional的本質,就是內部儲存了一個真實的值,在構造的時候,就直接判斷其值是否為空

Optional(T value)構造函數的源碼

? ? 1.1??of(T value)的源碼如下

public static <T> Optional<T> of(T value) {
?????return new Optional<>(value);
}

? ? 在of(T value)的實現源碼里也是調用了后遭方法,在這里可以看出,如果value值是空的,那么這里依舊會出現空指針異常的情況。
? ? 1.2??ofNullable(T value)?的源碼如下

public static <T> Optional<T> ofNullable(T value) {
?????return value == null ? empty() : of(value);
}

? ? 跟of(T value) 相比區別就是,如果value是null,of(T value)會報空指針異常,但是ofNullable(T value)不會拋出異常,而是直接返回一個EMPTY對象。這不是意味著of(T value) 一點用處都沒有的,如果我們的項目中并不想隱藏空指針異常,而是需要檢測到改情況并作特殊處理等情況的話就需要使用of(T value) 這個方法了。

? ??2、orElse(T other),orElseGet(Supplier<? extends T> other)和orElseThrow(Supplier<? extends X> exceptionSupplier)
? ? ? ? 這三個方法是在構造函數傳入的value為null的時候進行調用的。

user = Optional.ofNullable(user).orElse(createUser());
?user = Optional.ofNullable(user).orElseGet(() -> createUser());
Optional.ofNullable(user).orElseThrow(()->new Exception("不認識"));

? ???當user值不為null時,orElse函數依然會執行createUser()方法,而orElseGet函數并不會執行createUser()方法。
? ? orElseThrow,就是value值為null時,直接拋一個異常出去

3、map(Function<? super T, ? extends U> mapper)和flatMap(Function<? super T, Optional<U>> mapper)

public final class Optional<T> {
?????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));
?????????}
?????}?
}

? ? 這兩個函數主要的區別就是入參,map函數所接受的入參類型為Function<? super T, ? extends U>,而flapMap的入參類型為Function<? super T, Optional<U>>。

4、isPresent()和ifPresent(Consumer<? super T> consumer)

????isPresent()即判斷value值是否為空,而ifPresent就是在value值不為空時,做一些操作。這兩個函數是目前我在代碼中判空使用較多的。可以讓代碼更優雅一些。

public final class Optional<T> {
???? public boolean isPresent() {
?????????return value != null;
?????}?
?????public void ifPresent(Consumer<? super T> consumer) {
?????????if (value != null)
?????????????consumer.accept(value);
?????}
}

5、filter(Predicate<? super T> predicate)

public final class Optional<T> {
? ? Objects.requireNonNull(predicate);
?????if (!isPresent())
?????????return this;
?????else
?????????return predicate.test(value) ? this : empty();?
}

? ? filter方法通過接收一下predicate來對Optional中包含的值進行過濾,如果包含的值滿足條件,那么還是原樣返回,否則返回empty。
? ? 用法:
? ??????Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getAge()<=20);
? ? ? ? 如果user的age年齡小于等于20的,則返回。如果是大于20的,則返回一個EMPTY對象。

巧妙的運用Optional會提高代碼效率,使代碼變得更加優雅。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容