在Java中對一個空物件進行操作時,便會丟擲最常見的異常
NullPointerException
。為了改善這個問題,Java 8中提供了一個
java。util。Optional
型別。Optional類的Javadoc描述如下:這是一個可以為null的容器物件。如果值存在則
isPresent()
方法會返回true,呼叫
get()
方法會返回該物件。下面介紹Optional類的使用方法。 假如有一個像下面這樣的類層次結構:
class Department { private Employee employee; public Department(Employee employee) { this。employee = employee; } Employee getEmployee() { return employee; } } class Employee { private Girl girlFriend; public Employee(Girl girlFriend) { this。girlFriend = girlFriend; } Girl getGirlFriend() { return girlFriend; } } class Girl { private String name; public Girl(String name) { this。name = name; } String getName() { return name; } }
部門
Department
類包含一個員工
employee
屬性,型別為
Employee
,員工
Employee
類包含
girlFriend
屬性,型別為
Girl
。假如現在要獲取部門某個員工的女朋友,我們通常是這樣獲取的:
static String getGirlFriendName(Department department) { if (department != null) { Employee employee = department。getEmployee(); if (employee != null) { Girl girl = employee。getGirlFriend(); if (girl != null) { return girl。getName(); } return “單身汪”; } return “沒有員工”; } return “部門為空”; }
可以看到,在每次引用變數的屬性時,都要先判斷變數是否為空,如果不做該檢查將可能導致
NullPointerException
。下面我們將使用Optional來改善這種層層巢狀,囉嗦的程式碼。
建立Optional
建立一個Optional物件有好幾種方式:
建立一個空的Optional
我們可以使用靜態工廠方法
Optional。empty
,建立一個空的Optional物件:
Optional
根據非空值建立Optional
我們也可以使用靜態工廠方法
Optional。of
來建立一個非空物件的Optional物件:
Optional
如果employee為空,這段程式碼會立即丟擲一個
NullPointerException
。
建立可以為null的Optional
使用靜態工廠方法
Optional。ofNullable
,我們可以建立一個允許null值的Optional物件:
Optional
如果employee為空,對其呼叫
get
方法將丟擲
NoSuchElementException
。
Optional方法
Optional類包含了許多方法,下面介紹這些方法的使用。
isPresent
顧名思義,如果值存在返回true,否則返回false。如:
Optional
get
如果Optional有值則將其返回,否則丟擲
NoSuchElementException
。下面舉個丟擲
NoSuchElementException
的例子:
try { Optional。empty()。get(); } catch (Exception e) { e。printStackTrace(); }
程式碼將捕獲到 java。util。NoSuchElementException: No value present 異常。
ifPresent
如果Optional例項有值則為其呼叫
Consumer
(函式描述符為
T -> void
),否則不做處理。如:
girl。ifPresent(g -> System。out。println(“我有女朋友,名字是:” + g。getName()));
orElse
如果Optional例項有值則將其返回,否則返回
orElse
方法傳入的引數。如:
System。out。println(Optional。empty()。orElse(“There is no value present!”));
程式將輸出
There is no value present!
。
orElseGet
orElseGet
與
orElse
方法類似,
orElse
方法將傳入的字串作為預設值,而
orElseGet
方法可以接受
Supplier
(函式描述符為
() -> T
)來生成預設值。如:
System。out。println(Optional。empty()。orElseGet(() -> “There is no value present!”));
程式同樣輸出
There is no value present!
。
orElseThrow
如果有值則將其返回,否則丟擲
Supplier
介面建立的異常。如:
try { Optional。empty()。orElseThrow(NoSuchElementException::new);} catch (Exception e) { e。printStackTrace();}
程式碼將捕獲到 java。util。NoSuchElementException: No value present 異常。
map
如果Optional有值,則對其執行呼叫
Function
函式描述符為(
T -> R
)得到返回值。如果返回值不為null,則建立包含
Function
回值的Optional作為map方法返回值,否則返回空Optional。
Optional
flatMap
如果有值,為其執行
Function
函式返回Optional型別返回值,否則返回空Optional。
flatMap
與
map
方法類似,區別在於
flatMap
中的
Function
函式返回值必須是Optional。呼叫結束時,
flatMap
不會對結果用Optional封裝。如:
upperName = name。flatMap((value) -> Optional。of(value。toUpperCase()));System。out。println(upperName。orElse(“No value found”));
filter
filter個方法透過傳入
Predicate
(函式描述符為
T -> Boolean
)對Optional例項的值進行過濾。如:
Optional
方法輸出
Jane
。
實戰
介紹完Optional類的方法後,我們使用Optional改善一開始的程式碼:
static String getGirlFriendName(Department department) { Optional
整潔而又不失逼格。