我们都知道在Java语言中,接口(interface)只包含方法定义而没有具体实现,所有实现该接口的非抽象类必须提供接口方法的具体实现。让我们看个例子
public interface SimpleInterface{ public void doSomeWork();}class SimpleInterfaceImpl implements SimpleInterface{ @Override public void doSomeWork(){ System.out.println("Do Work implementation in the class"); } public static void main(String... args){ SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl(); simpObj.doSomeWork(); }}
现在,如果在SimpleInterface中添加一个新方法
public interface SimpleInterface { public void doSomeWork(); public void doSomeOtherWork();}
并进行编译,编译器将会报如下错误:
$javac SimpleInterface.javaSimpleInterface.java:18: error: SimpleInterfaceImpl is not abstract and does not override abstract method doSomeOtherWork() in SimpleInterfaceclass SimpleInterfaceImpl implements SimpleInterface{^1 error
这种限制使得几乎不可能对已有的接口和API进行扩展或改善。当在对Collections API增强,使其支持Java8的lambda表达式时,也遇到了同样的挑战。为了克服这种限制,一个新概念被引入,我们称之为默认方法(default methods)也被称为防御方法(defender methods)或虚拟扩展方法(virtual extension methods)
默认方法是有一些有默认的具体实现,能够帮助扩展接口的同时,避免破坏现有代码的方法。让我们看下例:public interface SimpleInterface { public void doSomeWork(); //A default method in the interface created using "default" keyword default public void doSomeOtherWork() { System.out.println("DoSomeOtherWorkementation in the interface"); }}class SimpleInterfaceImpl implements SimpleInterface { @Override public void doSomeWork() { System.out.println("Do Work implementation in the class"); } public static void main(String... args) { SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl(); simpObj.doSomeWork(); simpObj.doSomeOtherWork(); }}
编译运行得到如下输出:
Do Some Work implementation in the classDoSomeOtherWork implementation in the interface
需要我们注意的是当一个类实现了两个接口并且每个接口都声明了一个同样名称的默认方法。这种情况下编译器将报错。让我们用一个例子来解释:
public interface InterfaceWithDefaultMethod{ public void someMethod(); default public void someOtherMethod(){ System.out.println("Default implemetation in the interface"); }}public interface InterfaceWithAnotherDefMethod{ default public void someOtherMethod(){ System.out.println("Default implemetation in the interface"); }}
然后使用一个类实现上面的接口:
public class DefaultMethodSample implements InterfaceWithDefaultMethod, InterfaceWithAnotherDefMethod{ @Override public void someMethod(){ System.out.println("Some implemetation in the class"); } public static void main(String... args){ DefaultMethodSample def1 = new DefaultMethodSample(); def1.someMethod(); def1.someOtherMethod(); }}
编译时报如下错误。 Java通过这种方式来避免究竟该调用哪个实现的混乱。
本文翻译自:
更深入的了解Default Method请参考