成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《java 8 實(shí)戰(zhàn)》讀書筆記 -第九章 默認(rèn)方法

phoenixsky / 2385人閱讀

摘要:類或父類中聲明的方法的優(yōu)先級高于任何聲明為默認(rèn)方法的優(yōu)先級。只有聲明了一個(gè)默認(rèn)方法。由于比更加具體,所以編譯器會選擇中聲明的默認(rèn)方法。

如果在現(xiàn)存的接口上引入了非常多的新方法,所有的實(shí)現(xiàn)類都必須進(jìn)行改造,實(shí)現(xiàn)新方法,為了解決這個(gè)問題,Java 8為了解決這一問題引入了一種新的機(jī)制。Java 8中的接口現(xiàn)在支持在聲明方法的同時(shí)提供實(shí)現(xiàn),這聽起來讓人驚訝!通過兩種方式可以完成這種操作。其一,Java 8允許在接口內(nèi)聲明靜態(tài)方法。其二,Java 8引入了一個(gè)新功能,叫默認(rèn)方法,通過默認(rèn)方法你可以指定接口方法的默認(rèn)實(shí)現(xiàn)。

靜態(tài)方法可以存在于接口內(nèi)部
一、不斷演進(jìn)的API

默認(rèn)方法試它讓類庫的設(shè)計(jì)者放心地改進(jìn)應(yīng)用程序接口,無需擔(dān)憂對遺留代碼的影響,這是因?yàn)閷?shí)現(xiàn)更新接口的類現(xiàn)在會自動繼承一個(gè)默認(rèn)的方法實(shí)現(xiàn)。

不同類型的兼容性:二進(jìn)制、源代碼和函數(shù)行為
變更對Java程序的影響大體可以分成三種類型的兼容性,分別是:二進(jìn)制級的兼容、源代碼級的兼容,以及函數(shù)行為的兼容。

向接口添加新方法是二進(jìn)制級的兼容,但最終編譯實(shí)現(xiàn)接口的類時(shí)卻會發(fā)生編譯錯(cuò)誤。二進(jìn)制級的兼容性表示現(xiàn)有的二進(jìn)制執(zhí)行文件能無縫持續(xù)鏈接(包括驗(yàn)證、準(zhǔn)備和解析)和運(yùn)行。比如,為接口添加一個(gè)方法就是二進(jìn)制級的兼容,這種方式下,如果新添加的方法不被調(diào)用,接口已經(jīng)實(shí)現(xiàn)的方法可以繼續(xù)運(yùn)行,不會出現(xiàn)錯(cuò)誤。

簡單地說,源代碼級的兼容性表示引入變化之后,現(xiàn)有的程序依然能成功編譯通過。

最后,函數(shù)行為的兼容性表示變更發(fā)生之后,程序接受同樣的輸入能得到同樣的結(jié)果。比如,為接口添加新的方法就是函數(shù)行為兼容的,因?yàn)樾绿砑拥姆椒ㄔ诔绦蛑胁⑽幢徽{(diào)用(抑或該接口在實(shí)現(xiàn)中被覆蓋了)。

二、概述默認(rèn)方法

默認(rèn)方法由default修飾符修飾,并像類中聲明的其他方法一樣包含方法體。比如,你可以像下面這樣在集合庫中定義一個(gè)名為Sized的接口,在其中定義一個(gè)抽象方法size,以及一個(gè)默認(rèn)方法isEmpty:

public interface Sized { 
 int size(); 
 default boolean isEmpty() { 
 return size() == 0; 
 } 
}

第3章介紹的很多函數(shù)式接口,比如Predicate、Function以及Comparator也引入了新的默認(rèn)方法,比如Predicate.and或者Function.andThen(記住,函數(shù)式接口只包含一個(gè)抽象方法,默認(rèn)方法是種非抽象方法)。

個(gè)抽象類可以通過實(shí)例變量(字段)保存一個(gè)通用狀態(tài),而接口是不能有實(shí)例變量的。
三、默認(rèn)方法的使用模式 1.可選方法

你很可能也碰到過這種情況,類實(shí)現(xiàn)了接口,不過卻刻意地將一些方法的實(shí)現(xiàn)留白。我們以Iterator接口為例來說。Iterator接口定義了hasNext、next,還定義了remove方法。Java 8之前,由于用戶通常不會使用該方法,remove方法常被忽略。因此,實(shí)現(xiàn)Interator接口的類通常會為remove方法放置一個(gè)空的實(shí)現(xiàn),這些都是些毫無用處的模板代碼。

采用默認(rèn)方法之后,你可以為這種類型的方法提供一個(gè)默認(rèn)的實(shí)現(xiàn),這樣實(shí)體類就無需在自己的實(shí)現(xiàn)中顯式地提供一個(gè)空方法。比如,在Java 8中,Iterator接口就為remove方法提供了一個(gè)默認(rèn)實(shí)現(xiàn),如下所示:

interface Iterator { 
 boolean hasNext(); 
 T next(); 
 default void remove() { 
 throw new UnsupportedOperationException(); 
 }
2.行為的多繼承

類型的多繼承

利用正交方法的精簡接口

組合接口

繼承不應(yīng)該成為你一談到代碼復(fù)用就試圖倚靠的萬精油。比如,從一個(gè)擁有100個(gè)方法及字段的類進(jìn)行繼承就不是個(gè)好主意,因?yàn)檫@其實(shí)會引入不必要的復(fù)雜性。你完全可以使用代理有效地規(guī)避這種窘境,即創(chuàng)建一個(gè)方法通過該類的成員變量直接調(diào)用該類的方法。
四、解決沖突的規(guī)則 1.解決問題的三條規(guī)則

如果一個(gè)類使用相同的函數(shù)簽名從多個(gè)地方(比如另一個(gè)類或接口)繼承了方法,通過三條規(guī)則可以進(jìn)行判斷。

(1)類中的方法優(yōu)先級最高。類或父類中聲明的方法的優(yōu)先級高于任何聲明為默認(rèn)方法的優(yōu)先級。

(2)如果無法依據(jù)第一條進(jìn)行判斷,那么子接口的優(yōu)先級更高:函數(shù)簽名相同時(shí),優(yōu)先選擇擁有最具體實(shí)現(xiàn)的默認(rèn)方法的接口,即如果B繼承了A,那么B就比A更加具體。

(3)最后,如果還是無法判斷,繼承了多個(gè)接口的類必須通過顯式覆蓋和調(diào)用期望的方法,顯式地選擇使用哪一個(gè)默認(rèn)方法的實(shí)現(xiàn)。

2.沖突及如何顯式地消除歧義

對于上面提到的第三種情況,解決這種兩個(gè)可能的有效方法之間的沖突,沒有太多方案;你只能顯式地決定你希望在C中使用哪一個(gè)方法。為了達(dá)到這個(gè)目的,你可以覆蓋類C中的hello方法,在它的方法體內(nèi)顯式地調(diào)用你希望調(diào)用的方法。Java 8中引入了一種新的語法X.super.m(…),其中X是你希望調(diào)用的m方法所在的父接口。舉例來說,如果你希望C使用來自于B的默認(rèn)方法,它的調(diào)用方式看起來就如下所示:

public class C implements B, A { 
 void hello(){ 
 B.super.hello(); 
 } 
}
3.菱形繼承問題

讓我們考慮最后一種場景,它亦是C++里中最令人頭痛的難題。

public interface A{ 
 default void hello(){ 
 System.out.println("Hello from A"); 
 } 
} 

public interface B extends A { } 

public interface C extends A { } 

public class D implements B, C { 
 public static void main(String... args) { 
 new D().hello(); 
 } 
} 

這種問題叫“菱形問題”,因?yàn)轭惖睦^承關(guān)系圖形狀像菱形。這種情況下類D中的默認(rèn)方法到底繼承自什么地方 ——源自B的默認(rèn)方法,還是源自C的默認(rèn)方法?實(shí)際上只有一個(gè)方法聲明可以選擇。只有A聲明了一個(gè)默認(rèn)方法。由于這個(gè)接口是D的父接口,代碼會打印輸出“Hello from A”。

現(xiàn)在,我們看看另一種情況,如果B中也提供了一個(gè)默認(rèn)的hello方法,并且函數(shù)簽名跟A中的方法也完全一致,這時(shí)會發(fā)生什么情況呢?根據(jù)規(guī)則(2),編譯器會選擇提供了更具體實(shí)現(xiàn)的接口中的方法。由于B比A更加具體,所以編譯器會選擇B中聲明的默認(rèn)方法。如果B和C都使用相同的函數(shù)簽名聲明了hello方法,就會出現(xiàn)沖突,正如我們之前所介紹的,你需要顯式地指定使用哪個(gè)方法。順便提一句,如果你在C接口中添加一個(gè)抽象的hello方法(這次添加的不是一個(gè)默認(rèn)方法),會發(fā)生什么情況呢?你可能也想知道答案。

public interface C extends A { 
 void hello(); 
} 

這個(gè)新添加到C接口中的抽象方法hello比由接口A繼承而來的hello方法擁有更高的優(yōu)先級,因?yàn)镃接口更加具體。因此,類D現(xiàn)在需要為hello顯式地添加實(shí)現(xiàn),否則該程序無法通過編譯。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/74296.html

相關(guān)文章

  • java 8 實(shí)戰(zhàn)讀書筆記 -第十章 用Optional取代null

    摘要:但返回的是一個(gè)類型的對象,這意味著操作的結(jié)果是一個(gè)類型的對象。反之,如果對象存在,這次調(diào)用就會將其作為函數(shù)的輸入,并按照與方法的約定返回一個(gè)對象。 一、Optional 類入門 Java 8中引入了一個(gè)新的類java.util.Optional。變量存在時(shí),Optional類只是對類簡單封裝。變量不存在時(shí),缺失的值會被建模成一個(gè)空的Optional對象,由方法Optional.empt...

    時(shí)飛 評論0 收藏0
  • Java8實(shí)戰(zhàn)》-讀書筆記第一章(02)

    摘要:實(shí)戰(zhàn)讀書筆記第一章從方法傳遞到接著上次的,繼續(xù)來了解一下,如果繼續(xù)簡化代碼。去掉并且生成的數(shù)字是萬,所消耗的時(shí)間循序流并行流至于為什么有時(shí)候并行流效率比循序流還低,這個(gè)以后的文章會解釋。 《Java8實(shí)戰(zhàn)》-讀書筆記第一章(02) 從方法傳遞到Lambda 接著上次的Predicate,繼續(xù)來了解一下,如果繼續(xù)簡化代碼。 把方法作為值來傳遞雖然很有用,但是要是有很多類似與isHeavy...

    lushan 評論0 收藏0
  • java 8 實(shí)戰(zhàn)讀書筆記 -第三章 Lambda表達(dá)式

    摘要:利用前面所述的方法,這個(gè)例子可以用方法引用改寫成下面的樣子構(gòu)造函數(shù)引用對于一個(gè)現(xiàn)有構(gòu)造函數(shù),你可以利用它的名稱和關(guān)鍵字來創(chuàng)建它的一個(gè)引用。 第三章 Lambda表達(dá)式 函數(shù)式接口 函數(shù)式接口就是只定義一個(gè)抽象方法的接口,哪怕有很多默認(rèn)方法,只要接口只定義了一個(gè)抽象方法,它就仍然是一個(gè)函數(shù)式接口。 常用函數(shù)式接口 showImg(https://segmentfault.com/img...

    whinc 評論0 收藏0
  • java 8 實(shí)戰(zhàn)讀書筆記 -第十四章 函數(shù)式編程的技巧

    摘要:但是,最好使用差異化的類型定義,函數(shù)簽名如下其實(shí)二者說的是同一件事。后者的返回值和初始函數(shù)的返回值相同,即。破壞式更新和函數(shù)式更新的比較三的延遲計(jì)算的設(shè)計(jì)者們在將引入時(shí)采取了比較特殊的方式。四匹配模式語言中暫時(shí)并未提供這一特性,略。 一、無處不在的函數(shù) 一等函數(shù):能夠像普通變量一樣使用的函數(shù)稱為一等函數(shù)(first-class function)通過::操作符,你可以創(chuàng)建一個(gè)方法引用,...

    nemo 評論0 收藏0
  • java 8 實(shí)戰(zhàn)讀書筆記 -第七章 并行數(shù)據(jù)處理與性能

    摘要:正確使用并行流錯(cuò)用并行流而產(chǎn)生錯(cuò)誤的首要原因,就是使用的算法改變了某些共享狀態(tài)。高效使用并行流留意裝箱有些操作本身在并行流上的性能就比順序流差還要考慮流的操作流水線的總計(jì)算成本。 一、并行流 1.將順序流轉(zhuǎn)換為并行流 對順序流調(diào)用parallel方法: public static long parallelSum(long n) { return Stream.iterate(1L...

    劉福 評論0 收藏0
  • java 8 實(shí)戰(zhàn)讀書筆記 -第五章 使用流

    摘要:比如,你可以建立一個(gè),選出熱量超過卡路里的頭三道菜請注意也可以用在無序流上,比如源是一個(gè)。跳過元素流還支持方法,返回一個(gè)扔掉了前個(gè)元素的流。一般來說,應(yīng)該使用來對這種流加以限制,以避免打印無窮多個(gè)值。 一、篩選和切片 1.用謂詞篩選 Streams接口支持filter方法。該操作會接受一個(gè)謂詞(一個(gè)返回boolean的函數(shù))作為參數(shù),并返回一個(gè)包括所有符合謂詞的元素的流。例如篩選出所有...

    Richard_Gao 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<