Java8新特性之默認(rèn)方法和靜態(tài)方法
前言
在Java 8之前,默認(rèn)情況下,接口中的所有方法都是公共的和抽象的。但是這一限制在Java 8中被打破了,Java 8允許開發(fā)人員在接口中添加新方法,而無需在實(shí)現(xiàn)這些接口的類中進(jìn)行任何更改。
為什么會(huì)有默認(rèn)方法?
主要是為了方便擴(kuò)展已有接口;如果沒有默認(rèn)方法,假如給Java中的某個(gè)接口添加一個(gè)新的抽象方法,那么所有實(shí)現(xiàn)了該接口的類都得修改,影響將非常大。
舉個(gè)例子,Sortable <T>接口以及實(shí)現(xiàn)該接口的類SortableNumberCollection和SortableStringCollection。該接口有兩種方法:void sort(); 和T peek()。
public interface Sortable<T> { void sort(); T peek(); }
sort()方法用于對(duì)象排序,T peek()用于獲取指定元素,另外需要一個(gè)比較器類ObjectComparator來對(duì)對(duì)象進(jìn)行排序。
public class ObjectComparator implements Comparator<Comparable> { @Override public int compare(Comparable o1, Comparable o2) { return o1.compareTo(o2); } }
SortableStringCollection是一個(gè)自定義集合類可以進(jìn)行排序,并查看字符串指定元素,代碼如下:
public class SortableStringCollection implements Sortable<String> { private List<String> items = new ArrayList<>(); public void add(String item) { items.add(item); } @Override public void sort() { items.sort(new ObjectComparator()); } @Override public String peek() { return items.get(0); } }
同樣,SortableNumberCollection是一個(gè)自定義集合類,其中包含可以使用接口方法進(jìn)行排序和查看的數(shù)字列表指定元素,代碼如下:
public class SortableNumberCollection implements Sortable<Integer> { private List<Integer> items = new ArrayList<>(); public void add(Integer item) { items.add(item); } @Override public void sort() { items.sort(new ObjectComparator()); } @Override public Integer peek() { return items.get(0); } }
在Java8之前如果對(duì)接口Sortable<T>添加新方法:T sortAndPeek(),那么SortableStringCollection和
SortableNumberCollection都必須實(shí)現(xiàn)T sortAndPeek()方法。
Java8之后提供了一種新的實(shí)現(xiàn)方式,默認(rèn)方法 default method,我們可以對(duì)Sortable<T>進(jìn)行如下改造:
public interface Sortable<T> { void sort(); T peek(); default T sortAndPeek(){ // New 'default method' added in the interface sort(); return peek(); } }
同時(shí)SortableStringCollection和SortableNumberCollection類不需要任何更改。這樣可以減少我們對(duì)原有代碼的改動(dòng)。同時(shí)如果需要,還可以在實(shí)現(xiàn)此接口的任何類中重寫該方法T sortAndPeek()的默認(rèn)實(shí)現(xiàn)。
在下圖中我們看到default Method不通的標(biāo)識(shí):
在多繼承中使用默認(rèn)方法問題
如果兩個(gè)或多個(gè)接口具有相同的默認(rèn)方法簽名,并且一個(gè)類實(shí)現(xiàn)了這兩個(gè)接口,則將引發(fā)編譯時(shí)錯(cuò)誤。例如:
public interface Interface1 { void methodOne(String str); default void newMethod(){ System.out.println("Interface1: Newly added method"); } } public interface Interface2 { void methodTwo(String str); default void newMethod(){ System.out.println("Interface2: Newly added method"); } } public class InterfaceImplementation implements Interface1, Interface2{ @Override public void methodOne(String str) { System.out.println("Overridden methodOne: " + str); } @Override public void methodTwo(String str) { System.out.println("Overridden methodTwo: " + str ); } }
此時(shí)代碼會(huì)提示如下異常:
InterfaceImplementation inherits unrelated defaults for newMethod() from types Interface1 and Interface2
要解決此問題,我們將必須重寫類InterfaceImplementation中的方法:
public class InterfaceImplementation implements Interface1, Interface2{ @Override public void methodOne(String str) { System.out.println("Overridden methodOne: " + str); } // newMethod implemented to resolve the conflict. @Override public void newMethod() { System.out.println("InterfaceImplementation: Newly added method"); } @Override public void methodTwo(String str) { System.out.println("Overridden methodTwo: " + str ); } }
我們總結(jié)一下:
- 類中的方法優(yōu)先級(jí)最高。類或父類中聲明的方法的優(yōu)先級(jí)高于任何聲明為默認(rèn)方法的優(yōu)先級(jí)。
- 如果無法依據(jù)第一條進(jìn)行判斷,那么子接口的優(yōu)先級(jí)更高:函數(shù)簽名相同時(shí),優(yōu)先選擇擁有最具體實(shí)現(xiàn)的默認(rèn)方法的接口,即如果B繼承了A,那么B就比A更加具體。
- 最后,如果還是無法判斷,繼承了多個(gè)接口的類必須通過顯式覆蓋和調(diào)用期望的方法,顯式地選擇使用哪一個(gè)默認(rèn)方法的實(shí)現(xiàn)。
在Java 8中添加靜態(tài)方法
接口定義的靜態(tài)方法獨(dú)立于任何對(duì)象調(diào)用。所以,在調(diào)用靜態(tài)方法時(shí),不需要實(shí)現(xiàn)接口,也不需要接口的實(shí)例,
就像“默認(rèn)方法”一樣,“靜態(tài)方法”也可以添加到接口中。例如,我們可以添加一個(gè)靜態(tài)方法Direction getDefaultDirection(),該方法將返回默認(rèn)Direction,例如:
public interface Sortable<T> { Direction defaultDirection = Direction.DESC; enum Direction { ASC, DESC }; void sort(); T peek(); static Direction getDefaultDirection(){ // 'static method' added to the interface. return defaultDirection; } }
在上面的示例中,可以使用類引用來調(diào)用靜態(tài)Direction getDefaultDirection()方法:
Sortable.getDefaultDirection()
對(duì)默認(rèn)方法和靜態(tài)方法的一點(diǎn)思考
接口是設(shè)計(jì)模式中一種開閉原則的體驗(yàn),而java8賦予了接口新的特性,使得接口使用起來更加的得心應(yīng)手了,這也有助于我們更加內(nèi)聚自己的代碼結(jié)構(gòu)了。Java源碼中也有很多場(chǎng)景使用到了默認(rèn)方法,例如:Iterator接口,我們?cè)陂_發(fā)中可以多使用一些新的特性從而提高開發(fā)效率及增加代碼的健壯性。
public interface Iterable<T> { Iterator<T> iterator(); default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }
總結(jié)
到此這篇關(guān)于Java8新特性之默認(rèn)方法和靜態(tài)方法的文章就介紹到這了,更多相關(guān)Java8默認(rèn)方法和靜態(tài)方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java8接口的默認(rèn)方法
- Java8新特性之默認(rèn)方法(default)淺析
- 謹(jǐn)慎使用Java8的默認(rèn)方法
- Java8中新特性O(shè)ptional、接口中默認(rèn)方法和靜態(tài)方法詳解
- 一篇文章帶你認(rèn)識(shí)Java8接口的默認(rèn)方法
- 30分鐘入門Java8之默認(rèn)方法和靜態(tài)接口方法學(xué)習(xí)
- Java8默認(rèn)方法Default Methods原理及實(shí)例詳解
- java8新特性之接口默認(rèn)方法示例詳解
- Java8中的默認(rèn)方法(面試者必看)
- Java8新特性之默認(rèn)方法詳解
相關(guān)文章
Java控制臺(tái)輸入數(shù)組并逆序輸出的方法實(shí)例
這篇文章主要介紹了Java手動(dòng)輸入數(shù)組并逆向輸出的方法實(shí)例,需要的朋友可以參考下。2017-08-08SpringBoot JPA實(shí)現(xiàn)增刪改查、分頁(yè)、排序、事務(wù)操作等功能示例
本篇文章主要介紹了SpringBoot JPA實(shí)現(xiàn)增刪改查、分頁(yè)、排序、事務(wù)操作等功能示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03Java發(fā)送報(bào)文與接收?qǐng)?bào)文的實(shí)例代碼
這篇文章主要介紹了Java發(fā)送報(bào)文與接收?qǐng)?bào)文,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03java:程序包org.bouncycastle.jce.provider不存在問題及解決
這篇文章主要介紹了java:程序包org.bouncycastle.jce.provider不存在問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05java通過JFrame做一個(gè)登錄系統(tǒng)的界面完整代碼示例
這篇文章主要介紹了java通過JFrame做一個(gè)登錄系統(tǒng)的界面完整代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12Spring中@Autowired自動(dòng)注入map詳解
這篇文章主要介紹了Spring中@Autowired自動(dòng)注入map詳解, spring是支持基于接口實(shí)現(xiàn)類的直接注入的,支持注入map,list等集合中,不用做其他的配置,直接注入,需要的朋友可以參考下2023-10-10淺析SpringBoot微服務(wù)中異步調(diào)用數(shù)據(jù)提交數(shù)據(jù)庫(kù)的問題
這篇文章主要介紹了SpringBoot微服務(wù)中異步調(diào)用數(shù)據(jù)提交數(shù)據(jù)庫(kù)的問題,今天本文涉及到的知識(shí)點(diǎn)不難,都是很簡(jiǎn)單的crud操作,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07