Java8新特性之默認方法詳解
簡介
在Java之前,我們接觸到的接口,都是只定義方法,不實現(xiàn)方法
(你看下面這幾個人,像不像接口)
但是到了Java8就不一樣了,因為在接口中新增了默認方法
這樣的話,有些活,就可以交給接口自己去做了,而不用實現(xiàn)類去做(Java你這是在收買人心?。?/p>
我們下面以問答的形式來介紹默認方法的相關知識點(據(jù)說問答模式可以讓人更好地記憶?)
正文
什么是默認方法
默認方法是接口中用default修飾的方法,其中包含方法內(nèi)容
比如下面這個:
public?interface?InterfaceDemo?{ ? ?// 普通方法,只定義,不實現(xiàn) ? ?void?oldFun(); ? ?// 默認方法,又定義,又實現(xiàn) ? ?default?void?newFun(){ ? ? ? ?System.out.println("newFun"); ? } }
為啥要提供默認方法呢?
為了向后兼容(這也是導致Java變得臃腫的原因之一)。
因為升級系統(tǒng)時,難免會有一些新功能需要加入,此時如果接口類新增了方法,那么實現(xiàn)類就必須同步修改實現(xiàn);
這樣工作量還是很大的,而且很容易出錯。
所以Java8開始,推出了接口的默認方法這個功能,使得接口升級變得更加平滑
比如下面的代碼:InterfaceDemo就是上面那個接口
public?class?UserDemo?implements?InterfaceDemo{ ? ?@Override ? ?public?void?oldFun() { ? ? ? ?System.out.println("oldFun"); ? } ? ?public?static?void?main(String[]?args) { ? ? ? ?UserDemo?demo?=?new?UserDemo(); ? ? ? ?/** ? ? ? ??* InterfaceDemo升級后,新增了newFun方法 ? ? ? ??* 但是由于newFun是默認方法,有提供實現(xiàn)內(nèi)容 ? ? ? ??* 所以這里的子類 UserDemo就可以直接使用 ? ? ? ? ?*/ ? ? ? ?demo.newFun(); ? } }
我們可以看到,UserDemo沒有實現(xiàn)新的方法newFun(),但是也可以編譯運行,并直接調用newFun()
這就是默認方法的好處:對實現(xiàn)類來說是無痛升級的
如果不提供呢?
不提供的話,接口類升級時,系統(tǒng)有兩個選擇
實現(xiàn)類升級:
實現(xiàn)類老老實實地按照接口升級后的方法,進行同步修改實現(xiàn),但是工作量大
實現(xiàn)類不升級:
實現(xiàn)類不升級也是可以的,只要不引入接口類的新版本就可以了,那么這個時候系統(tǒng)還是可以運行的,這沒啥問題。但是誰能保證一輩子都不更新系統(tǒng)呢?如果更新系統(tǒng)時,接口類庫升級到新版本,那么編譯還是通不過
主要針對誰?
接口的默認方法主要是針對類庫設計者
實現(xiàn)了默認方法的接口和抽象類有區(qū)別嗎
區(qū)別沒有之前那么多,但還是有的:
抽象類單繼承,接口類多實現(xiàn)
抽象類中的屬性定義時不需要初始化,接口類的屬性定義時要初始化(默認修飾符為public static final)
是不是可以說Java現(xiàn)在也實現(xiàn)了多重繼承?
可以這么說。
但是現(xiàn)在面臨的一個新問題,就是多重繼承帶來的二義性問題,有點類似之前介紹的致命方塊(也叫菱形問題)
如下面的UML圖所示
比如上面這種,你無法知道A會調用哪個接口的fun方法
所以編譯器會報錯:
com.jalon.java8.defaultmethod.A?inherits?unrelated?defaults?for?fun()?from?types?com.jalon.java8.defaultmethod.B?and?com.jalon.java8.defaultmethod.C
解決辦法:
先覆寫fun方法
再顯示聲明調用哪個接口的fun方法
代碼如下:
public?class?A?implements?B,C{ ? ?@Override ? ?public?void?fun(){ ? ? ? ?// 顯示調用B的默認方法 ? ? ? ?B.super.fun(); ? } ? ?public?static?void?main(String[]?args) { ? ? ? ?A?a?=?new?A(); ? ? ? ?// 這里會打印B的fun ? ? ? ?a.fun(); ? } } interface?D{ ? ?default?void?fun(){ ? ? ? ?System.out.println("D"); ? } } interface?B?extends?D{ ? ?@Override ? ?default?void?fun(){ ? ? ? ?System.out.println("B"); ? } } interface?C?extends?D{ ? ?@Override ? ?default?void?fun(){ ? ? ? ?System.out.println("C"); ? } }
總結
什么是默認方法:接口中用default修飾且包含方法內(nèi)容的方法
為什么要提供默認方法:向后兼容,使系統(tǒng)平滑過渡;主要針對類庫設計者
多重繼承帶來的問題:二義性,也叫菱形問題;解決辦法就是子類盡量覆寫默認方法并顯式聲明調用哪個方法(實際上這個問題很少出現(xiàn),因為它屬于編譯錯誤,寫代碼時隨時可以發(fā)現(xiàn))
到此這篇關于Java8新特性之默認方法的文章就介紹到這了,更多相關Java8默認方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
不寫mybatis的@Param有的報錯有的卻不報錯問題分析
這篇文章主要為大家介紹了不寫mybatis的@Param有的報錯有的卻不報錯問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09解決java.net.SocketTimeoutException: Read timed out的問題
這篇文章主要介紹了解決java.net.SocketTimeoutException: Read timed out的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06SpringMVC @RequestMapping注解應用方法示例講解
通過@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關于SpringMVC中@RequestMapping注解用法的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-09-09Springboot基于BCrypt非對稱加密字符串的實現(xiàn)
本文主要介紹了Springboot基于BCrypt非對稱加密字符串的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04詳解基于java的Socket聊天程序——客戶端(附demo)
這篇文章主要介紹了詳解基于java的Socket聊天程序——客戶端(附demo),客戶端設計主要分成兩個部分,分別是socket通訊模塊設計和UI相關設計。有興趣的可以了解一下。2016-12-12java JDBC系列教程之JDBC類的簡析與JDBC的基礎操作
這篇文章主要介紹了java JDBC系列教程之JDBC類的簡析與JDBC的基礎操作,本文分步驟通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07