本篇文章為大家展示了如何深度解析java8新特性Optional,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
下面以jdk1.8.0_111源碼為例
public final class Optional<T> {}
Optional是一個為了解決NullPointerException設計而生可以包含對象也可以包含空的容器對象。封裝了很多對空處理的方法也增加了filter、map這樣的檢索利器,其中函數式編程會有種炫酷到爆的感覺。
基礎測試用例對象:
public class Java8OptionalTest {
List<String> stringList = null;
ICar car = new WeiLaiCar();
}
public class WeiLaiCar implements ICar {
Integer wheels = new Integer(4);
}Api中提供的4種optional
最核心的當屬Optional對象,泛型的引入支持了所有對象類型,又增加對常用場景下的double\int\long進行擴展。重點介紹一下Optional對象的方法其他三個類似。
public final class Optional<T> {
public final class OptionalDouble {
public final class OptionalInt {
public final class OptionalLong {
@FunctionalInterface
Predicate\Consumer\Supplier三個接口都是函數式接口
靜態方法of
private Optional() {
this.value = null;
}構造方法被private,不能new但提供了of這樣的靜態方法去初始化類;
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}1、empty支持你去創建一個空的optional類,這樣的類直接get()會報錯:java.util.NoSuchElementException: No value present
2、of(x)傳入的對象不能為null,而ofNullable(x)是支持傳入null的對象,一般用這兩個比較多。
present 方法
isPresent是用來判斷optional中對象是否為null,ifPresent的參數是當對象不為null時執行的lamdba表達式。
public boolean isPresent() {
return value != null;
}
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}示例詳解介紹了ifPresent特性:
Java8OptionalTest test = new Java8OptionalTest();
Optional<Java8OptionalTest> optional = Optional.of(test);
pringTest(optional.isPresent());
//true
optional.ifPresent( a -> pringTest(a.getCar().getClass().getName()));
//com.ts.util.optional.WeiLaiCar
optional.ifPresent( a -> Optional.ofNullable(a.getStringList()).ifPresent(b -> pringTest("StringList:" + (b == null))));//第一級的ifPresent是存在test對象,所以執行了lambda表達式,而第二級的ifPresent的stringList是null,所以沒有執行表達式
optional.ifPresent( a -> Optional.ofNullable(a.getCar()).ifPresent(b -> pringTest("car:" + (b == null))));
//car:false
//第二級ifPresent的car對象是存在的,所以第二級的表達式執行了
map 方法
源碼提供了兩種map和flatMap。
map方法的參數是個當包含的對象不為null時才執行的lambda表達式,返回該表達式執行結果的封裝optional對象,同理支持鏈式調用,逐層深入和遞歸遞進很像;
flatMap區別在于lambda表達式的返回結果必須主動包裹Optinoal,否則報錯
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));
}
}測試示例:
Java8OptionalTest test = new Java8OptionalTest();
Optional<Java8OptionalTest> optional = Optional.of(test);
Optional opt1 = optional.map( a -> a.getCar());
pringTest(opt1.get());
//com.ts.util.optional.WeiLaiCar@5d6f64b1
int wheel = 0;//傳統null判斷寫法
if(test != null){
if(test.getCar() != null){//實際業務里面層級也許會超過3層
wheel = test.getCar().getWheelCount();
}
}
pringTest("傳統:"+wheel);
//傳統:4
Optional opt2 = optional.map( a -> a.getCar()).map(b -> b.getWheelCount());//Optional支持下的寫法
pringTest("optinal:"+opt2.get());
//optinal:4
Optional opt3 = optional.map( a -> a.getStringList()).map(b -> b.size());
pringTest(opt3);
//Optional.empty
Optional opt4 = optional.flatMap(a -> Optional.of(a.getCar()));//主動包裹Optional對象
pringTest(opt4);
//Optional[com.ts.util.optional.WeiLaiCar@5d6f64b1]
Optional opt5 = optional.flatMap(a -> Optional.of(a.getCar())).flatMap(b -> Optional.ofNullable(b.getWheelCount()));
pringTest(opt5);
//Optional[4]
filter 方法
源碼如下:
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
filter方法傳入一個斷言語句條件的lambda表達式,返回一個原對象的optional包裝,所以支持鏈式調用;只要記住這三點你便掌握如何使用了。
看下面的例子:Java8OptionalTest test = new Java8OptionalTest();
Optional<Java8OptionalTest> optional = Optional.of(test);
Optional result = optional.filter( a -> a.getCar() != null).filter( b -> b.getClass().getName() != null);
pringTest(result.isPresent()? result.get().getClass().getName(): result.isPresent());
//com.ts.util.Java8OptionalTest
Optional result1 = optional.filter( a -> a.getStringList() != null);
pringTest(result1.get());
//java.util.NoSuchElementException: No value presentorElse 方法
Api提供了三個方法。
orElse 當optional內對象為null就返回這個參數,比較像很多默認值設置;
orElseGet 基本同orElse,區別是傳入參數支持lambda表達式,返回的就是表達式執行結果;
orElseThrow 也是傳入lambda表達式,但是表達式是拋出異常
public T orElse(T other) {
return value != null ? value : other;
}
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}測試用例如下:
Java8OptionalTest one = null;
Java8OptionalTest test = new Java8OptionalTest();
Optional<Java8OptionalTest> optional = Optional.ofNullable(one);
pringTest(optional);
//Optional.empty
pringTest(optional.orElse(test));
//com.ts.util.Java8OptionalTest@5197848c
pringTest(optional.orElseGet(() -> new Java8OptionalTest()));
//com.ts.util.Java8OptionalTest@5d6f64b1
pringTest(optional.orElseThrow(() -> new RuntimeException("orElseThrow")));
//java.lang.RuntimeException: orElseThrowJava主要應用于:1. web開發;2. Android開發;3. 客戶端開發;4. 網頁開發;5. 企業級應用開發;6. Java大數據開發;7.游戲開發等。
上述內容就是如何深度解析java8新特性Optional,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。