在學習集合代碼時發(fā)現(xiàn)在Iterable接口中使用了default關鍵字。
default關鍵字介紹
default是在java8中引入的關鍵字,也可稱為Virtual
extension methods——虛擬擴展方法。是指,在接口內部包含了一些默認的方法實現(xiàn)(也就是接口中可以包含方法體,這打破了Java之前版本對接口的語法限制),從而使得接口在進行擴展的時候,不會破壞與接口相關的實現(xiàn)類代碼。
為什么要有這個特性?
首先,之前的接口是個雙刃劍,好處是面向抽象而不是面向具體編程,缺陷是,當需要修改接口時候,需要修改全部實現(xiàn)該接口的類,目前的java8之前的集合框架沒有foreach方法,通常能想到的解決辦法是在JDK里給相關的接口添加新的方法及實現(xiàn)。然而,對于已經(jīng)發(fā)布的版本,是沒法在給接口添加新方法的同時不影響已有的實現(xiàn)。所以引進的默認方法。他們的目的是為了解決接口的修改與現(xiàn)有的實現(xiàn)不兼容的問題。
如何使用default關鍵字?
1、調用父接口實現(xiàn)
創(chuàng)建接口Interface1,并且在接口Interface1中定義默認方法helloWorld()。
public interface Interface1{
default void helloWorld() {
System.out.println("hi i'm from Interface1");
}
}
這時可以編寫一個類實現(xiàn)接口Interface1,并調用接口中定義的默認方法helloWorld(),代碼如下
/**
* 實現(xiàn)接口Interface1
*/
public class MyImplement implements Interface1{
public static void main(String[] args) {
MyImplement myImplement = new MyImplement();
//直接調用helloWorld()方法
myImplement.helloWorld();
}
}
可以看到,執(zhí)行的結果為我們之前在接口Interface1中定義的默認方法。

此時的類圖為

2、同時繼承兩個接口
創(chuàng)建接口Interface2,接口Interface2中也定義了默認方法helloWorld()。
public interface Interface2{
default void helloWorld() {
System.out.println("hi i'm from Interface2");
}
}
這時候讓類MyImplement同時實現(xiàn)Interface1和Interface2,代碼如下:
/**
* 實現(xiàn)接口Interface1,Interface2
*/
public class MyImplement implements Interface1,Interface2{
public static void main(String[] args) {
MyImplement myImplement = new MyImplement();
//直接調用helloWorld()方法
myImplement.helloWorld();
}
}
此時會發(fā)現(xiàn)編譯器報錯,報錯信息如下:

發(fā)生這種情況的原因是,實現(xiàn)類MyImplement即實現(xiàn)了接口Interface1又實現(xiàn)了接口Interface2,恰巧兩個接口中都定義可相同的默認方法。說白了就是編譯器此時已經(jīng)被干懵了,當我們在MyImplement類中調用方法時,它不知道該去調用Interface1的默認方法還是去調用Interface2的方法。解決方法就是在實現(xiàn)類中實現(xiàn)該方法。代碼如下
public class MyImplement implements Interface1,Interface2 {
@Override
public void helloWorld() {
System.out.println("hi i'm from MyImplement");
}
public static void main(String[] args) {
MyImplement myImplement = new MyImplement();
myImplement.helloWorld();
}
}
執(zhí)行代碼控制臺輸出如下:

此時的類圖為

3、類優(yōu)先于接口
此時創(chuàng)建一個實現(xiàn)類MyImplement2,該實現(xiàn)類不僅繼承了MyImplement1并且實現(xiàn)了Interface2。
實現(xiàn)類MyImplement2的代碼如下
public class MyImplement2 extends MyImplement implements Interface2{
public static void main(String[] args) {
MyImplement2 myImplement2 = new MyImplement2();
myImplement2.helloWorld();
}
}
此時的類圖為

此時在實現(xiàn)類MyImplement2中調用helloWorld()方法,到底執(zhí)行的是MyImplement中的方法還是執(zhí)行Interface2中的方法?
答:因為類優(yōu)先于接口,所以將會執(zhí)行MyImplement中的方法。
執(zhí)行結果如下
