JDK8新特性03-Optional API

Optional類介紹

一句話介紹Optional類:使用JDK8的Optional類來防止NPE(空指針異常)問題。

Optional類源碼介紹

在這裏插入圖片描述

Optional的屬性以及創建Optional容器的方法

// 1、創建出一個Optional容器,容器裏邊並沒有裝載着對象
    private static final Optional<?> EMPTY = new Optional<>();

    // 2、代表着容器中的對象
    private final T value;

    // 3、私有構造方法
    private Optional() {
        this.value = null;
    }

    // 4、得到一個Optional容器,Optional沒有裝載着對象
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    // 5、私有構造方法(帶參數),參數就是具體的要裝載的對象,如果傳進來的對象爲null,拋出異常
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    // 5.1、如果傳進來的對象爲null,拋出異常
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }


    // 6、創建出Optional容器,並將對象(value)裝載到Optional容器中。
    // 傳入的value如果爲null,拋出異常(調用的是Optional(T value)方法)
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // 創建出Optional容器,並將對象(value)裝載到Optional容器中。
    // 傳入的value可以爲null,如果爲null,返回一個沒有裝載對象的Optional對象
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

所以可以得出創建Optional容器有三種方式:

  • 調用empty()方法
 // Optional的三種創建方式-empty
 Optional<Object> empty = Optional.empty();
  • 調用of()方法,傳入的對象不可以爲null,否則拋出NullPointerException
 // Optional的三種創建方式-of
 Optional<Object> o = Optional.of(new Object());
  • 調用ofNullable()方法,傳入的對象可以爲null
 // Optional的三種創建方式-ofNullable
 Optional<Insurance> objectOptional = Optional.ofNullable(null);

Optional容器簡單的方法

get方法

// 得到容器中的對象,如果爲null就拋出異常
public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

isPresent方法

// 判斷容器中的對象是否爲null
public boolean isPresent() {
    return value != null;
}

orElse方法

// 如果容器中的對象存在,則返回。否則返回傳遞進來的參數
public T orElse(T other) {
    return value != null ? value : other;
}

Optional容器進階用法

ifPresent方法

//如果容器中的對象存在,則調用accept方法
public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
        consumer.accept(value);
}

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

orElseGet方法

// 如果對象存在,則直接返回,否則返回由Supplier接口的實現用來生成默認值
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}


@FunctionalInterface
public interface Supplier<T> {
    T get();
}

orElseThrow方法

// 如果存在,則返回。否則拋出supplier接口創建的異常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

filter方法

// 如果容器中的對象存在,並且符合過濾條件,返回裝載對象的Optional容器,否則返回一個空的Optional容器
public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if (!isPresent())
        return this;
    else
        return predicate.test(value) ? this : empty();
}


// 接口
@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
}

map方法

// 如果容器的對象存在,則對其執行調用mapping函數得到返回值。然後創建包含mapping返回值的Optional,否則返回空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));
    }
}


// 接口
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

Optional的總結

filter,map或flatMap一個函數,函數的參數拿到的值一定不是null。所以我們通過filter,map 和 flatMap之類的函數可以將其安全的進行變換,最後通過orElse系列,get,isPresent 和 ifPresent將其中的值提取出來。
其實吧,用Optional類也沒有簡化很多的代碼,只是把NPE異常通過各種方法隱藏起來(包裝了一層)。通過Lambda表達式可以讓我們處理起來更加"優雅"一些。

使用Optional前後對比

到這裏我們可以做一下和傳統方式的對比

		//傳統判空
		User userNull = null;
        if(userNull != null){
            System.out.println(userNull.getId());
        }else{
            System.out.println("UNKNOWN");
        }
        
		//使用Optional判空
		Optional<User> userNull1 = Optional.ofNullable(userNull);
        if(userNull1.isPresent()){
            System.out.println(userNull.getId());
        }else{
            System.out.println("UNKNOWN");
        }
        
        //學會Optional和lambda方法後
        Optional<User> userNull2 = Optional.ofNullable(userNull);
        userNull2.map(user1 -> user1.getId()).orElse("UNKNOWN");

這裏再使用3Y的代碼做一下對比

public static void main(String[] args) {
    User user = new User();
    user.setName("Java3y");
    System.out.println(test(user));
}

// 以前的代碼v1
public static String test2(User user) {
    if (user != null) {
        String name = user.getName();
        if (name != null) {
            return name.toUpperCase();
        } else {
            return null;
        }
    } else {
        return null;
    }
}

// 以前的代碼v2
public static String test3(User user) {
    if (user != null && user.getName() != null) {
        return user.getName().toUpperCase();
    } else {
        return null;
    }
}

// 現在的代碼
public static String test(User user) {
    return Optional.ofNullable(user)
            .map(user1 -> user1.getName())
            .map(s -> s.toUpperCase()).orElse(null);
}

總結Optional類到此結束 , 有問題可以到3Y這裏的博客看一下.
原文地址給女朋友講解什麼是Optional【JDK 8特性】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章