Java 8中允许接口中包含具有具体实现的方法,该方法称为 “默认方法”,默认方法使用 default 关键字修饰。
一个例子
/** * @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 } }
默认方法的继承
默认的方法也可以被继承
/** * @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!"); } }
接口和抽象类(类优先原则)
当接口继承行为发生冲突时,类的方法声明优先于接口默认方法,无论该方法是具体的还是抽象的。
/** * @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 欢迎来留言啊!!!