Java 8中容許接口中包含具備具體實現的方法,該方法稱爲 「默認方法」,默認方法使用 default 關鍵字修飾。java
一個例子
/** * @author black貓 * @date 2019-11-27 * 一個接口 */ public interface MyInterface<T> { /*** * sayHi 抽象方法 * @param name * @return */ T sayHi(String name); /*** * sayHello 默認方法 * @param name * @return */ default String sayHello(String name) { return "Hello :" + name; } } /** * @author black貓 * @date 2019-11-28 * 實現類 */ public class MyInterfaceImpl implements MyInterface<String> { /*** * sayHi 方法 * @param name * @return */ @Override public String sayHi(String name) { return "Hi :" +name; } } /*** * @author black貓 * @date 2019-11-27 * 接口的實現類 測試 */ public class MyInterfaceTest { /*** * 測試默認方法 */ @Test public void test01() { MyInterface myInterface = new MyInterfaceImpl(); // MyInterfaceImpl類並無實現 sayHello 方法就能夠調用 MyInterface接口的靜態方法 System.out.println(myInterface.sayHello("Tom")); // Hello :Tom System.out.println(myInterface.sayHi("Jim")); // Hi :Jim } }
默認方法的重寫,修改MyInterfaceImpl
/** * @author black貓 * @date 2019-11-28 * 實現類 */ public class MyInterfaceImpl implements MyInterface<String> { /*** * sayHi 方法 * @param name * @return */ @Override public String sayHi(String name) { return "Hi :" +name; } /*** * sayHello 默認方法 * @param name * @return */ @Override public String sayHello(String name) { return "hello: "+name+" by MySuperClass..."; } } /** * @author black貓 * @date 2019-11-27 * 接口的實現類 測試 */ public class MyInterfaceTest { /*** * 測試 */ @Test public void test01() { MyInterface myInterface = new MyInterfaceImpl(); System.out.println(myInterface.sayHello("Tom")); // hello: Tom by MySuperClass... System.out.println(myInterface.sayHi("Jim")); // Hi :Jim } }
默認方法的繼承
默認的方法也能夠被繼承ide
/** * @author black貓 * @date 2019-11-27 * 接口的實現類 測試 */ public class MyInterfaceTest { @Test public void test02() { new Interface02(){}.printHello(); // Interface01 hello! new Interface03(){}.printHello(); // Interface03 hello! new Interface04(){ @Override public void printHello() { System.out.println("Interface04 hello!"); } }.printHello(); // Interface04 hello! } } // Interface01接口裏面有一默認方法 interface Interface01 { default void printHello() { System.out.println("Interface01 hello!"); } } /*** * Interface02 繼承 Interface01 默認方法被繼承 */ interface Interface02 extends Interface01 { } /*** * Interface03 繼承 Interface01 默認方法繼承後重寫默認方法 */ interface Interface03 extends Interface01 { @Override default void printHello() { System.out.println("Interface03 hello!"); } } /*** * Interface04 繼承 Interface01 默認方法繼承後從新定義爲抽象方法 */ interface Interface04 extends Interface01 { @Override void printHello(); }
默認方法的多繼承
當接口的默認方法有衝突時,須要本身重寫調用方法,也能夠使用 InterfaceName.super.methodName(); 的方式手動調用須要的接口默認方法。測試
// Interface05接口有一個默認方法 printHello interface Interface05 { default void printHello() { System.out.println("Interface05 hello!"); } } // Interface06接口有一個默認方法 printHi interface Interface06 { default void printHi() { System.out.println("Interface06 hi!"); } } // Interface07接口有兩個默認方法 printHello 和 printHi interface Interface07 { //默認方法 printHello default void printHello() { System.out.println("Interface07 hello!"); } //默認方法 printHi default void printHi() { System.out.println("Interface07 hi!"); } } // Class08 繼承 Interface05和Interface06 class Class08 implements Interface05, Interface06 { } // 報錯 Class09 繼承 Interface06和Interface07 // 默認方法printHi衝突 必須選擇重寫一個父類的printHi //class Class09 implements Interface06, Interface07 { // //} // Class10 繼承 Interface06和Interface07 // 默認方法衝突 選擇一個重寫 class Class10 implements Interface06, Interface07 { @Override public void printHi() { //覆寫存在歧義的方法,能夠使用 InterfaceName.super.methodName(); 的方式手動調用須要的接口默認方法。 Interface06.super.printHi(); Interface07.super.printHi(); System.out.println("Class10 hi!"); } }
接口和抽象類(類優先原則)
當接口繼承行爲發生衝突時,類的方法聲明優先於接口默認方法,不管該方法是具體的仍是抽象的。code
/** * @author black貓 * @date 2019-11-28 * */ public class AbstractTest { public static void main(String[] args) { Class001 class001 = new Class001(); class001.printHello(); // hello interface01... class001.printHi(); // hi abstract01... } } // 繼承抽象類Abstract001 而且實現接口Interface001 class Class001 extends Abstract001 implements Interface001 { @Override public void printHello() { Interface001.super.printHello(); } } // 一個接口有兩個默認方法 interface Interface001 { default void printHello() { System.out.println("hello interface01..."); } default void printHi() { System.out.println("hi interface01..."); } } //一個抽象類 有一個抽象方法 一個實現的方法 abstract class Abstract001 { abstract void printHello(); public void printHi() { System.out.println("hi abstract01..."); } }
接口的靜態方法
接口的靜態方法和類的靜態方法使用一致繼承
/** * @author black貓 * @date 2019-11-28 * Java 8 還在容許在接口中定義靜態方法。 */ public class StaticTest { public static void main(String[] args) { Interface.printHelloWorld(); } } /** * Interface接口有一個靜態方法 printHelloWorld */ interface Interface { /*** * 靜態方法 */ static void printHelloWorld() { System.out.println("Interface11 printHelloWorld..."); } }
java8的接口默認方法下降了實現類之間的耦合,當須要爲一個接口添加方法時,沒必要對全部實現類都修改。能夠爲接口添加新的默認方法,而不會破壞已有的接口的實現,也爲升級舊接口且保持向後兼容提供了新的途徑。
文章首發於黑貓のBlog歡迎來留言啊!!!接口