Java8中新特性O(shè)ptional、接口中默認(rèn)方法和靜態(tài)方法詳解
前言
毫無疑問,Java 8是Java自Java 5(發(fā)布于2004年)之后的最重要的版本。這個(gè)版本包含語言、編譯器、庫、工具和JVM等方面的十多個(gè)新特性。
Java 8是Java的一個(gè)重大版本,有人認(rèn)為,雖然這些新特性領(lǐng)Java開發(fā)人員十分期待,但同時(shí)也需要花不少精力去學(xué)習(xí)。下面本文就給大家詳細(xì)介紹了Java8中新特性O(shè)ptional、接口中默認(rèn)方法和靜態(tài)方法的相關(guān)內(nèi)容,話不多說了,來一起看看詳細(xì)的介紹吧。
Optional
Optional 類(java.util.Optional) 是一個(gè)容器類,代表一個(gè)值存在或不存在,原來用 null 表示一個(gè)值不存在,現(xiàn)在 Optional 可以更好的表達(dá)這個(gè)概念。并且可以避免空指針異常。
常用方法:
Optional.of(T t): 創(chuàng)建一個(gè) Optional 實(shí)例。Optional.empty(): 創(chuàng)建一個(gè)空的 Optional 實(shí)例。Optional.ofNullable(T t)若 t 不為 null,創(chuàng)建 Optional 實(shí)例,否則創(chuàng)建空實(shí)例。isPresent(): 判斷是否包含值。orElse(T t): 如果調(diào)用對象包含值,返回該值,否則返回t。orElseGet(Supplier s):如果調(diào)用對象包含值,返回該值,否則返回 s 獲取的值。map(Function f)如果有值對其處理,并返回處理后的Optional,否則返回Optional.empty()flatMap(Function mapper)與 map 類似,要求返回值必須是Optional。
下面引用ImportNew的一段內(nèi)容來告訴我們?nèi)绾握_使用Optional。比如千萬不要寫成這樣子:
public static String getName(User u) {
Optional<User> user = Optional.ofNullable(u);
if (!user.isPresent())
return "Unknown";
return user.get().name;
}
這樣改寫非但不簡潔,而且其操作還是和第一段代碼一樣。無非就是用isPresent方法來替代u==null。這樣的改寫并不是Optional正確的用法,我們再來改寫一次。
public static String getName(User u) {
return Optional.ofNullable(u)
.map(user->user.name)
.orElse("Unknown");
}
這樣才是正確使用Optional的姿勢。那么按照這種思路,我們可以安心的進(jìn)行鏈?zhǔn)秸{(diào)用,而不是一層層判斷了。看一段代碼:
public static String getChampionName(Competition comp) throws IllegalArgumentException {
if (comp != null) {
CompResult result = comp.getResult();
if (result != null) {
User champion = result.getChampion();
if (champion != null) {
return champion.getName();
}
}
}
throw new IllegalArgumentException("The value of param comp isn't available.");
}
由于種種原因(比如:比賽還沒有產(chǎn)生冠軍、方法的非正常調(diào)用、某個(gè)方法的實(shí)現(xiàn)里埋藏的大禮包等等),我們并不能開心的一路comp.getResult().getChampion().getName()到底。而其他語言比如kotlin,就提供了在語法層面的操作符加持:comp?.getResult()?.getChampion()?.getName() 所以講道理在Java里我們怎么辦!
讓我們看看經(jīng)過Optional加持過后,這些代碼會(huì)變成什么樣子。
public static String getChampionName(Competition comp) throws IllegalArgumentException {
return Optional.ofNullable(comp)
.map(c->c.getResult())
.map(r->r.getChampion())
.map(u->u.getName())
.orElseThrow(()->new IllegalArgumentException("The value of param comp isn't available."));
}
這就很舒服了。Optional的魅力還不止于此,Optional還有一些神奇的用法,比如Optional可以用來檢驗(yàn)參數(shù)的合法性。
public void setName(String name) throws IllegalArgumentException {
this.name = Optional.ofNullable(name).filter(User::isNameValid)
.orElseThrow(()->new IllegalArgumentException("Invalid username."));
}
上面代碼引用importnew—Java8 如何正確使用 Optional。
接口中的默認(rèn)方法與靜態(tài)方法
Java8接口中可以添加靜態(tài)方法,也可以添加默認(rèn)方法,默認(rèn)方法用 default修飾。
public interface Fun<T> {
default void getName(){
System.out.println("hello world");
}
static void getAge(){
System.out.println("nine");
}
}
若一個(gè)接口中定義了一個(gè)默認(rèn)方法,他的實(shí)現(xiàn)類的一個(gè)父類定義了具有相同名稱和參數(shù)列表的方法。則調(diào)用該實(shí)現(xiàn)類的時(shí)候執(zhí)行父類中的方法。
public class TestF {
public void getName(){
System.out.println("TestF");
}
}
public interface TestInterface {
default void getName(){
System.out.println("hello world");
}
}
public class Test extends TestF implements TestInterface{
public static void main(String[] args) {
Test t = new Test();
t.getName();//輸出的是TestF
}
}
若一個(gè)實(shí)現(xiàn)類實(shí)現(xiàn)了兩個(gè)接口,如果一個(gè)父接口提供一個(gè)默認(rèn)方法,而另一個(gè)父接口也提供了一個(gè)具有相同名稱和參數(shù)列表的方法(不管方法是否是默認(rèn)方法),那么必須覆蓋該方法來解決沖突,否則會(huì)報(bào)錯(cuò)。
public interface TestInterface {
default void getName(){
System.err.println("hello world");
}
}
public interface TestInterface1 {
void getName();
}
public class Test1 implements TestInterface, TestInterface1{
public void getName(){
System.out.println("Tes1F");
}
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
idea中Java實(shí)體類怎樣生成序列化的版本號的方法
這篇文章主要介紹了idea中Java實(shí)體類怎樣生成序列化的版本號的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
SpringBoot實(shí)現(xiàn)國際化過程詳解
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)國際化過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
使用Spring和Redis創(chuàng)建處理敏感數(shù)據(jù)的服務(wù)的示例代碼
許多公司處理的用戶敏感數(shù)據(jù)由于法律限制不能永久存儲,根據(jù)規(guī)定,這些數(shù)據(jù)的存儲時(shí)間不能超過預(yù)設(shè)期限,并且最好在用于服務(wù)目的之后就將其刪除,解決這個(gè)問題有多種可能的方案,在本文中,我想展示一個(gè)利用 Spring 和 Redis 處理敏感數(shù)據(jù)的應(yīng)用程序的簡化示例2025-04-04
spring-boot List轉(zhuǎn)Page的方法步驟
這篇文章主要介紹了spring-boot List轉(zhuǎn)Page的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
swing中Tree與滾動(dòng)條用法實(shí)例分析
這篇文章主要介紹了swing中Tree與滾動(dòng)條用法,以實(shí)例形式分析了java基于swing實(shí)現(xiàn)圖形界面的使用技巧,需要的朋友可以參考下2015-09-09

