爲了防止無良網站的爬蟲抓取文章,特此標識,轉載請註明文章出處。LaplaceDemon/SJQ。html
http://www.cnblogs.com/shijiaqi1066/p/5713941.html java
Objects工具類提供了一些靜態方法,用於支持補充對象的一些基礎操做。該類在Java 1.7被引入,部分方法1.8引入。某些方法對對象檢查null提供必定的支持。express
static <T> int |
該方法用於比較兩個對象。 bash |
static boolean |
若參數深度相等,則返回true,不然返回false。 app |
static boolean |
若是參數相等,則返回true,不然返回false。 ide |
static int |
計算函數參數列表的Hash值。 |
static int |
若參數爲null,則返回0。不然返回對象的Hash值。 |
static boolean |
若是對象爲null,則返回true;若是對象不爲null,則返回false。 |
static boolean |
若是對象不爲null,則返回true;若是對象爲null,則返回false。 |
static <T> T |
檢查對象不爲null。 |
static <T> T |
檢查對象不爲null。若爲null,則拋出被定製的過的NullPointerException異常。 |
static <T> T |
檢查對象不爲null。若爲null,則拋出被定製的過的NullPointerException異常。 |
static String |
|
static String |
返回參數的字符串,若是對象爲null,則返回第二個參數nullDefault。 |
Java中常常會遇到這樣的表達式:
String version = computer.getSoundcard().getUSB().getVersion();
這種表達式很爽,但若是getSoundcard、getUSB、getVersion可能會返回Null指針,那麼這段代碼就必須這樣寫:
String version = "UNKNOWN"; if(computer != null){ Soundcard soundcard = computer.getSoundcard(); if(soundcard != null){ USB usb = soundcard.getUSB(); if(usb != null){ version = usb.getVersion(); } } }
因此,若是沒法肯定方法返回的對象是非空的,則咱們須要時時刻刻都須要提防調用的方法是否返回null,以防止NullPointerException。
受到Haskell和Scala的啓發,Java8引入了java.util.Optional<T>
類。這是一個容器類。該容器只包含一個值,要麼改值存在,要麼不存在。
空的Optional對象
Optional<Soundcard> sc = Optional.empty();
of 工廠方法
爲非null的值建立一個Optional。Optional對象的構造方法。若是傳入參數爲null,則拋出NullPointerException 。
//調用工廠方法建立Optional實例 Optional<String> name = Optional.of("Sanaulla");
//傳入參數爲null,拋出NullPointerException. Optional<String> someNull = Optional.of(null);
ofNullable 工廠方法
爲指定的值建立一個Optional。若值爲null,則返回一個空的Optional。ofNullable與of方法類似,惟一的區別是能夠接受參數爲null的狀況。
//下面建立了一個不包含任何值的Optional實例 //例如,值爲'null' Optional empty = Optional.ofNullable(null);
isPresent
若是值存在返回true,不然返回false。
get
能夠返回Optional容器裏的對象。若Optional有值則將其返回;若沒有值,拋出NoSuchElementException。
//執行下面的代碼會輸出:No value present try { //在空的Optional實例上調用get(),拋出NoSuchElementException System.out.println(empty.get()); } catch (NoSuchElementException ex) { System.out.println(ex.getMessage()); }
get方法與isPresent方法組合能夠這樣使用:
//isPresent方法用來檢查Optional實例中是否包含值 if (name.isPresent()) { //在Optional實例內調用get()返回已存在的值 System.out.println(name.get());//輸出Sanaulla }
可是注意,這種組合跟null
檢測沒有什麼區別,因此並不提倡這樣使用Optional。
ifPresent
若是Optional實例有值則爲其調用從參數傳入consumer,不然不作處理。
要理解ifPresent方法,首先須要瞭解Consumer類。簡答地說,Consumer類包含一個抽象方法。該抽象方法對傳入的值進行處理,但沒有返回值。Java8支持不用接口直接經過lambda表達式傳入參數。
若是Optional實例有值,調用ifPresent()能夠接受接口段或lambda表達式。相似下面的代碼:
//ifPresent方法接受lambda表達式做爲參數。 //lambda表達式對Optional的值調用consumer進行處理。 name.ifPresent((value) -> { System.out.println("The length of the value is: " + value.length()); });
orElse
若是Optional實例有值則將其返回,不然返回orElse方法傳入的參數。
//若是值不爲null,orElse方法返回Optional實例的值。 //若是爲null,返回傳入的消息。 //輸出:There is no value present! System.out.println(empty.orElse("There is no value present!")); //輸出:Sanaulla System.out.println(name.orElse("There is some value!"));
orElseGet
orElseGet與orElse方法相似,區別在於獲得的默認值。orElse方法將傳入的字符串做爲默認值,orElseGet方法能夠接受Supplier接口的實現用來生成默認值。示例以下:
//orElseGet與orElse方法相似,區別在於orElse傳入的是默認值, //orElseGet能夠接受一個lambda表達式生成默認值。 //輸出:Default Value System.out.println(empty.orElseGet(() -> "Default Value")); //輸出:Sanaulla System.out.println(name.orElseGet(() -> "Default Value"));
orElseThrow
若是有值則將其返回,不然拋出supplier接口建立的異常。
在orElseGet方法中,咱們傳入一個Supplier接口。然而,在orElseThrow中咱們能夠傳入一個lambda表達式或方法,若是值不存在來拋出異常。示例以下:
try { //orElseThrow與orElse方法相似。與返回默認值不一樣, //orElseThrow會拋出lambda表達式或方法生成的異常 empty.orElseThrow(ValueAbsentException::new); } catch (Throwable ex) { //輸出: No value present in the Optional instance System.out.println(ex.getMessage()); }
ValueAbsentException定義以下:
class ValueAbsentException extends Throwable { public ValueAbsentException() { super(); } public ValueAbsentException(String msg) { super(msg); } @Override public String getMessage() { return "No value present in the Optional instance"; } }
map
若是Optional讀寫沒有值,則該方法直接返回空的Optional對象。
若是Optional對象有值,則對其執行調用mapping函數獲得返回值。
若是返回值爲null,則返回空Optional對象。
若是返回值不爲null,則建立包含mapping返回值的Optional做爲map方法返回值。
例:
//map方法執行傳入的lambda表達式參數對Optional實例的值進行修改。 //爲lambda表達式的返回值建立新的Optional實例做爲map方法的返回值。 Optional<String> upperName = name.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found"));
flatMap
若是有值,爲其執行mapping函數返回Optional類型返回值,不然返回空Optional。
注意:flatMap方法的mapping函數必須是Optional。
例:
// flatMap與map(Function)很是相似,區別在於傳入方法的lambda表達式的返回類型。 // map方法中的lambda表達式返回值能夠是任意類型,在map函數返回以前會包裝爲Optional。 // 但flatMap方法中的lambda表達式返回值必須是Optionl實例。 upperName = name.flatMap((value) -> Optional.of(value.toUpperCase())); System.out.println(upperName.orElse("No value found"));
辨析flatMap方法與map方法
flatMap方法與map方法相似。
區別在於:
- map方法的map函數返回值能夠是任何類型T。
- flatMap方法中的map函數返回值必須是Optional。調用結束時,flatMap不會對結果用Optional封裝。
filter
該方法經過傳入lambda表達式對Optional實例的值進行過濾。若是有值而且知足斷言條件返回包含該值的Optional,不然返回空Optional。
例:
//filter方法檢查給定的Option值是否知足某些條件。 //若是知足則返回同一個Option實例,不然返回空Optional。 Optional<String> longName = name.filter((value) -> value.length() > 6); System.out.println(longName.orElse("The name is less than 6 characters"));//輸出Sanaulla //另外一個例子是Optional值不知足filter指定的條件。 Optional<String> anotherName = Optional.of("Sana"); Optional<String> shortName = anotherName.filter((value) -> value.length() > 6); //輸出:name長度不足6字符 System.out.println(shortName.orElse("The name is less than 6 characters"));
總結Optional類的各個方法。如下是一個完整的示例:
public class OptionalDemo { public static void main(String[] args) { //建立Optional實例,也能夠經過方法返回值獲得。 Optional<String> name = Optional.of("Sanaulla"); //建立沒有值的Optional實例,例如值爲'null' Optional empty = Optional.ofNullable(null); //isPresent方法用來檢查Optional實例是否有值。 if (name.isPresent()) { //調用get()返回Optional值。 System.out.println(name.get()); } try { //在Optional實例上調用get()拋出NoSuchElementException。 System.out.println(empty.get()); } catch (NoSuchElementException ex) { System.out.println(ex.getMessage()); } //ifPresent方法接受lambda表達式參數。 //若是Optional值不爲空,lambda表達式會處理並在其上執行操做。 name.ifPresent((value) -> { System.out.println("The length of the value is: " + value.length()); }); //若是有值orElse方法會返回Optional實例,不然返回傳入的錯誤信息。 System.out.println(empty.orElse("There is no value present!")); System.out.println(name.orElse("There is some value!")); //orElseGet與orElse相似,區別在於傳入的默認值。 //orElseGet接受lambda表達式生成默認值。 System.out.println(empty.orElseGet(() -> "Default Value")); System.out.println(name.orElseGet(() -> "Default Value")); try { //orElseThrow與orElse方法相似,區別在於返回值。 //orElseThrow拋出由傳入的lambda表達式/方法生成異常。 empty.orElseThrow(ValueAbsentException::new); } catch (Throwable ex) { System.out.println(ex.getMessage()); } //map方法經過傳入的lambda表達式修改Optonal實例默認值。 //lambda表達式返回值會包裝爲Optional實例。 Optional<String> upperName = name.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found")); //flatMap與map(Funtion)很是類似,區別在於lambda表達式的返回值。 //map方法的lambda表達式返回值能夠是任何類型,可是返回值會包裝成Optional實例。 //可是flatMap方法的lambda返回值老是Optional類型。 upperName = name.flatMap((value) -> Optional.of(value.toUpperCase())); System.out.println(upperName.orElse("No value found")); //filter方法檢查Optiona值是否知足給定條件。 //若是知足返回Optional實例值,不然返回空Optional。 Optional<String> longName = name.filter((value) -> value.length() > 6); System.out.println(longName.orElse("The name is less than 6 characters")); //另外一個示例,Optional值不知足給定條件。 Optional<String> anotherName = Optional.of("Sana"); Optional<String> shortName = anotherName.filter((value) -> value.length() > 6); System.out.println(shortName.orElse("The name is less than 6 characters")); } }
上述代碼輸出以下:
Sanaulla No value present The length of the value is: 8 There is no value present! Sanaulla Default Value Sanaulla No value present in the Optional instance SANAULLA SANAULLA Sanaulla The name is less than 6 characters
最後,讓咱們解決Null調用這個問題:
String version = computer.getSoundcard().getUSB().getVersion();
首先設計的類,類中方法的須要返回Optional對象。
public class Computer { private Optional<Soundcard> soundcard; public Optional<Soundcard> getSoundcard() { ... } ... } public class Soundcard { private Optional<USB> usb; public Optional<USB> getUSB() { ... } } public class USB{ public String getVersion(){ ... } }
如下是一種錯誤的實例。這段代碼沒法經過編譯。
String version = computer.map(Computer::getSoundcard)
.map(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
首先computer是Optional類型,Optional類型經過Computer:getSoundcard,該方法返回Optional類型,再包裝進map方法,因此最後返回了Optional<Optional<T>>類型,該類型進入到下一個map函數中,參數沒法匹配。因此編譯不過。
使用flatMap方法控制返回類型,以保障鏈式調用。
String version = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
爲了防止無良網站的爬蟲抓取文章,特此標識,轉載請註明文章出處。LaplaceDemon/SJQ。