一、什么是默認方法,為什么要有默認方法
簡單說,就是接口可以有實現(xiàn)方法,而且不需要實現(xiàn)類去實現(xiàn)其方法。只需在方法名前面加個default關(guān)鍵字即可。
為什么要有這個特性?首先,之前的接口是個雙刃劍,好處是面向抽象而不是面向具體編程,缺陷是,當需要修改接口時候,需要修改全部實現(xiàn)該接口的類,目前的java 8之前的集合框架沒有foreach方法,通常能想到的解決辦法是在JDK里給相關(guān)的接口添加新的方法及實現(xiàn)。然而,對于已經(jīng)發(fā)布的版本,是沒法在給接口添加新方法的同時不影響已有的實現(xiàn)。所以引進的默認方法。他們的目的是為了解決接口的修改與現(xiàn)有的實現(xiàn)不兼容的問題。
簡單的例子:一個接口A,Clazz類實現(xiàn)了接口A。
public interface A {
default void foo(){
System.out.println("Calling A.foo()");
}
}
public class Clazz implements A {
public static void main(String[] args){
Clazz clazz = new Clazz();
clazz.foo();//調(diào)用A.foo()
}
}
代碼是可以編譯的,即使Clazz類并沒有實現(xiàn)foo()方法。在接口A中提供了foo()方法的默認實現(xiàn)。
二、java 8抽象類與接口對比
這一個功能特性出來后,很多同學都反應了,java 8的接口都有實現(xiàn)方法了,跟抽象類還有什么區(qū)別?其實還是有的,請看下表對比。。
相同點 |
不同點 |
1.都是抽象類型; 2.都可以有實現(xiàn)方法(以前接口不行); 3.都可以不需要實現(xiàn)類或者繼承者去實現(xiàn)所有方法,(以前不行,現(xiàn)在接口中默認方法不需要實現(xiàn)者實現(xiàn)) |
1.抽象類不可以多重繼承,接口可以(無論是多重類型繼承還是多重行為繼承); 2.抽象類和接口所反映出的設(shè)計理念不同。其實抽象類表示的是"is-a"關(guān)系,接口表示的是"like-a"關(guān)系; 3.接口中定義的變量默認是public static final 型,且必須給其初值,所以實現(xiàn)類中不能重新定義,也不能改變其值;抽象類中的變量默認是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。 |
三、多重繼承的沖突說明
由于同一個方法可以從不同接口引入,自然而然的會有沖突的現(xiàn)象,默認方法判斷沖突的規(guī)則如下:
1.一個聲明在類里面的方法優(yōu)先于任何默認方法(classes always win)
2.否則,則會優(yōu)先選取最具體的實現(xiàn),比如下面的例子 B重寫了A的hello方法。
輸出結(jié)果是:Hello World from B
如果想調(diào)用A的默認函數(shù),則用到新語法X.super.m(...),下面修改C類,實現(xiàn)A接口,重寫一個hello方法,如下所示:
public class C implements A{
@Override
public void hello(){
A.super.hello();
}
public static void main(String[] args){
new C().hello();
}
}
輸出結(jié)果是:Hello World from A
四、總結(jié)
默認方法給予我們修改接口而不破壞原來的實現(xiàn)類的結(jié)構(gòu)提供了便利,目前java 8的集合框架已經(jīng)大量使用了默認方法來改進了,當我們最終開始使用Java 8的lambdas表達式時,提供給我們一個平滑的過渡體驗。也許將來我們會在API設(shè)計中看到更多的默認方法的應用。