Java 8 新特性:4-Optional類
(原)
先看看上面的說明:
/** * A container object which may or may not contain a non-null value. * If a value is present, {@code isPresent()} will return {@code true} and * {@code get()} will return the value. *Optional是一個容器對象,它可能包含,也可能不包含一個非空的值,如果這個值存在,isPresent方法將返回true,get方法將會返回它本身 * <p>Additional methods that depend on the presence or absence of a contained * value are provided, such as {@link #orElse(java.lang.Object) orElse()} * (return a default value if value not present) and * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block * of code if the value is present). *Optional提供一些額外的方法,這些方法依賴於它所包含的對象存在與否,例如orElse如果這個包含的對象不存在,將會返回一個默認值和ifPresent方法,如果包含的值存在,則會執行方法塊中的內容 * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a> * class; use of identity-sensitive operations (including reference equality * ({@code ==}), hash code, or synchronization) on instances of * {@code Optional} may have unpredictable results and should be avoided. *這是一個基於值的class類,對於同一性(特性)敏感的操作 (包含引用的相等性如:==),同一性的hashcode或者同步等等、對optional實例可能會產生不可預料的結果,這種結果應該被避免。 * @since 1.8 */
再看看該類:
public final class Optional<T>
這裏一個final類
這是一個基於值的類,上面給出了什麽叫基於值,上面給出的鏈接地址不全,看這裏:
http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html
這裏說的是基於值的類需要滿足以下幾點:
1、 final類型和不可變的(可能會包含可變對象的引用)
2、 有equals、hashCode、toString方法的實現,它是通過實例的狀態計算出來的,而並不會通過其它的對象或變量去計算。
3、 不會使用身份敏感的操作,比如在二個實例之間引用相等性、hashCode或者內在的鎖。
4、 判斷二個值相等僅僅通過equal方法,而不會通過==去判斷。
5、 它不提供構造方法,它通過工廠方法創建它的實例,這不保證返回實例的一致性。
6、 當它們相等時,它是可以自由替換的。如果x和y 調用equal方法返回true,那麽可以將x和y任意交換,它的結果不會產生任何變化。
然後再回來看Optional,你能看到它是私有的:
private Optional() { this.value = null; }
在它的所有方法中,如果要創建Optional對象,先看看它常用的三個方法。
empty方法回一個空的 Optional對象。
of方法接收一個T參數,T必需為非null值,返回一個Optional對象。
ofNullable方法接收一個T參數,如果T為null,它會調用empty方法,如果不為null則調用of方法。
再看看這二個方法:
isPresent: 如果這個對象的值不為null返回true,否則返回false。
get:如果這個值存在,則返回這個值,如果這個值為null,則拋出異常。
在使用中,這二個方法基本是成對出現的,下面來看一個例子。
String str = "hello"; Optional<String> strValue = Optional.of(str); System.out.println("part1-------------------"); if(str != null){ System.out.println(str); } System.out.println("part2-------------------"); if(strValue.isPresent()){ System.out.println(strValue.get()); }
這裏,part1和part2的代碼是等價的,Optional還提供了一種更簡單的方法
strValue.ifPresent(s -> System.out.println(s));
ifPresent方法接收一個consumer函數式接口(之前介紹過),將自己的非空的邏輯寫進去。Optioanal該方法更加簡潔。
orElse方法:接收一個參數,如果存在,返回這個值本身,否則返回返回這個參數。
orElseGet方法:接收一個Supplier,如果存在,返回這個值本身,否則返回Supplier
對象。
map方法:接收一個Function,如果Optioanal為null則拋出異常(所以這裏創建Optional對象時建議用Optional.ofNullable()),如果為空值則返回空,如果不為空則返回Function的返回值。
(例如:一個對象Obj,有一個List屬性,如果List有值,返回List,否則返回空集合,可以這麽寫(
Parent parent = new Parent(); Optional<Parent> parentVal = Optional.ofNullable(parent); System.out.println(parentVal.map(m -> m.getList()).orElse(Collections.emptyList()));
)
Optioanal通常作為方法的返回值來使用,它可以有效的規避返回null的結果,如果一個類需要序列化,當Optional作為參數類型或是成員變量類型是有問題的。因為Optional沒有實現序列化,所以Optioanl通常不被建議作為參數或常量使用。
下面給出一些Optional常用的例子:
package com.demo.jdk8; import java.util.Collections; import java.util.List; import java.util.Optional; public class Test6 { public static void main(String[] args) { String str = "hello"; Optional<String> strValue = Optional.of(str); System.out.println("part1-------------------"); if(str != null){ System.out.println(str); } System.out.println("part2-------------------"); if(strValue.isPresent()){ System.out.println(strValue.get()); } System.out.println("part3-------------------"); strValue.ifPresent(s -> System.out.println(s)); System.out.println("part4-------------------"); Optional<String> op = Optional.ofNullable(null); System.out.println(op.orElse("hahahaha")); System.out.println("part5-------------------"); Optional<String> opt = Optional.ofNullable("nihao"); System.out.println(op.orElseGet(() -> "hehehe")); System.out.println("part6-------------------"); System.out.println(opt.map(m -> m + "123").orElseGet(() -> "world")); System.out.println("part7-------------------"); Parent parent = new Parent(); // List<Object> list = Arrays.asList("張三","李四"); // parent.setList(list); Optional<Parent> parentVal = Optional.ofNullable(parent); System.out.println(parentVal.map(m -> m.getList()).orElse(Collections.emptyList())); } public void test(Optional optional){ } } class Parent{ private List<Object> list; public List<Object> getList() { return list; } public void setList(List<Object> list) { this.list = list; } }
例子請看這裏:https://github.com/LeeScofield/java8
Java 8 新特性:4-Optional類