這篇文章主要講解了“Java8默認(rèn)方法會(huì)破壞用戶的代碼嗎”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java8默認(rèn)方法會(huì)破壞用戶的代碼嗎”吧!
我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、福綿ssl等。為上1000+企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的福綿網(wǎng)站制作公司
起初看來(lái),默認(rèn)方法給Java虛擬機(jī)的指令集帶來(lái)了很多新的特性。最終,開發(fā)庫(kù)的人能夠在不帶來(lái)客戶端代碼的兼容性問(wèn)題的情況下,升級(jí)API。使用 默認(rèn)方法,任何實(shí)現(xiàn)庫(kù)接口的類都自動(dòng)適應(yīng)接口引入的默認(rèn)方法。一旦用戶更新了他實(shí)現(xiàn)的類,就能夠很簡(jiǎn)單使用更有意義的方法來(lái)覆蓋原有默認(rèn)方法。更好的是, 用戶可以在覆蓋方法時(shí)候,調(diào)用接口的默認(rèn)實(shí)現(xiàn),同時(shí)增加業(yè)務(wù)邏輯。
到現(xiàn)在為止,一切都是很好。但是,在創(chuàng)建接口的時(shí)候增加默認(rèn)方法可能使得Java代碼不兼容。這個(gè)從下面的例子可以很容易弄明白。我們假設(shè)一個(gè)庫(kù)需要它的一個(gè)接口的作為輸入:
interface SimpleInput { void foo(); void bar(); } abstract class SimpleInputAdapter implements SimpleInput { @Override public void bar() { // some default behavior ... } }
Java 8之前,類似于上面聯(lián)合使用一個(gè)接口和一個(gè)適配器類的方式,是Java程序語(yǔ)言中一種非常常用的設(shè)計(jì)模式。該適配器通常由庫(kù)提供者提供,用于節(jié)省庫(kù)的使用者的某些操作。但是,如果采用接口的方式提供,就類似允許多重繼承了。
我們進(jìn)一步假設(shè)一個(gè)用戶使用了如下的適配器:
class MyInput extends SimpleInputAdapter { @Override public void foo() { // do something ... } @Override public void bar() { super.bar(); // do something additionally ... } }
通過(guò)這種實(shí)現(xiàn)方式,我們最終可以和庫(kù)進(jìn)行交互。注意我們是怎樣覆蓋bar方法,并為默認(rèn)的實(shí)現(xiàn)增加額外的功能的。
如果將該庫(kù)移植到Java 8,將會(huì)發(fā)生什么呢?首先,該庫(kù)很大可能性會(huì)廢棄適配器類,而使用默認(rèn)方法提供該功能。最終,該接口的形式類似如下所示:
interface SimpleInput { void foo(); default void bar() { // some default behavior } }
使用這個(gè)新的接口,用戶可以更新他的代碼,采用默認(rèn)方法來(lái)代替原來(lái)的適配器類。通過(guò)使用接口代替適配器類的***的結(jié)果是,該類可以繼承 (extend)其它的類,而不是特定的適配器?,F(xiàn)在我們進(jìn)行實(shí)踐,移植MyInput類使其使用默認(rèn)方法。因?yàn)槲覀儸F(xiàn)在能繼承其它類了,所以我們繼承一 個(gè)第三方的基礎(chǔ)類。我們這里不需要關(guān)心這個(gè)基礎(chǔ)類的作用,我們可以假設(shè)這個(gè)對(duì)我們的功能是有意義的。
class MyInput extends ThirdPartyBaseClass implements SimpleInput { @Override public void foo() { // do something ... } @Override public void bar() { SimpleInput.super.bar(); // do something additionally ... } }
為了實(shí)現(xiàn)原始類相似的功能,我們使用Java 8的新的語(yǔ)法來(lái)調(diào)用指定接口的默認(rèn)方法。同時(shí),將我們方法中的一些邏輯移到基礎(chǔ)類中去。此時(shí),你可能拍著我的肩膀說(shuō),這是一次非常好的重構(gòu)!
我們相當(dāng)成功的使用了該庫(kù)。但是,維護(hù)人員需要增加另一個(gè)接口來(lái)提供更多的功能。該接口被 ComplexInput 接口所代替,這個(gè)接口繼承自 SimpleInput 接口,并增加了新的方法。因?yàn)槟J(rèn)方法通常來(lái)說(shuō)是可以很安全的添加的,因此,維護(hù)人員覆蓋了 SimpleInput 的默認(rèn)方法,提供了一個(gè)更好的默認(rèn)方法。畢竟,這對(duì)于采用適配器類的方式來(lái)說(shuō)是很平常的事情。
interface ComplexInput extends SimpleInput { void qux(); @Override default void bar() { SimpleInput.super.bar(); // so complex, we need to do more ... } }
新的特性帶來(lái)了非常好的效果以至于維護(hù) ThirdPartyBaseClass 的人也決定依賴該庫(kù)。為了完成這項(xiàng)工作,它在 ThirdPartyLibrary 中實(shí)現(xiàn)了 ComplexInput 接口。
但是這對(duì) MyInput 類來(lái)說(shuō)意味著什么呢?為了隱式的實(shí)現(xiàn) ComplexInput 接口,可繼承 ThirdPartyBaseClass 類,但是調(diào)用 SimpleInput 的默認(rèn)方法突然變成非法的了。結(jié)果,用戶的代碼不能通過(guò)編譯。現(xiàn)在這種調(diào)用是被禁止的,因?yàn)镴ava認(rèn)為這種在非直接子類中調(diào)用父類的父類的方法是非法 的。你只能在 ComplexInput 中去調(diào)用該默認(rèn)方法,但是,這要求你顯示的在MyInput中實(shí)現(xiàn)該接口。對(duì)于庫(kù)的用戶來(lái)說(shuō),這種改變不是所預(yù)期的!
更奇怪的是,Java運(yùn)行時(shí)卻不做這種限制。JVM的校驗(yàn)器是允許一個(gè)編譯好的類去調(diào)用 SimpleInput::foo 方法的,即使該類是通過(guò)繼承更新后的 ThirdPartyBaseClass,從而隱式的實(shí)現(xiàn)了ComplexClass。這種限制只存在于編譯器中。
感謝各位的閱讀,以上就是“Java8默認(rèn)方法會(huì)破壞用戶的代碼嗎”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java8默認(rèn)方法會(huì)破壞用戶的代碼嗎這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!