本文主要介紹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特性】