java 8 之前,接口中只能声明抽象方法,比如:
package Default; public interface OldInterface { void existingMethod(); }
java 8 提供了一种新的方法,称之为default方法,即允许你在接口中提供一些方法的默认实现,而不是只能声明抽象方法,所以在java 8的支持下,你可以这样定义接口。
我们在OldInterface接口中添加了一个新方法newDefaultMethod,并且把该方法声明为default方法。
package Default; public interface OldInterface { void existingMethod(); default void newDefaultMethod() { System.out.println("default new default Method"); } }
package Default; public class OldInterfaceImplOne implements OldInterface { @Override public void existingMethod() { System.out.println("Implement existing method version: 1"); } }
package Default; public class Main { public static void main(String[] args) { OldInterface oi = new OldInterfaceImplOne(); oi.existingMethod(); oi.newDefaultMethod(); } }
输出结果如下:
Implement existing method version: 1 default new default Method
可以看到,我们的实现类中并没有提供newDefaultMethod的实现,但是因为接口中提供了newDefaultMethod的默认实现,所以最后在main方法调用的时候输出的结果是由默认实现提供的。
那这个default修饰符会不会改变以前那些实现该接口的类呢?
答案是并不会,如果我们在实现类中重写newDefaultMethod,
package Default; public class OldInterfaceImplOne implements OldInterface { @Override public void existingMethod() { System.out.println("Implement existing method version: 1"); } @Override public void newDefaultMethod() { System.out.println("Implement new Default method version: 1"); } }
输出结果如下:
Implement existing method version: 1 Implement new Default method version: 1可以发现newDefaultMethod方法已经被覆写, 所以default方法对过去那些实现该接口的实现类是向下兼容的,不会影响之前实现的类的功能。
那假如有一个实现类实现了两个接口,两个接口有着一个同名的default类会发生什么情况?
package Default; public interface AnotherOldInterface { void anotherExistingMethod(); default void newDefaultMethod() { System.out.println("another default new default Method"); } }
package Default; public class OldInterfaceImplOne implements OldInterface, AnotherOldInterface { @Override public void existingMethod() { System.out.println("Implement existing method version: 1"); } @Override public void anotherExistingMethod() { System.out.println("Another Implement existing method version: 1"); } }
package Default; public class Main { public static void main(String[] args) { OldInterface oi = new OldInterfaceImplOne(); oi.existingMethod(); oi.newDefaultMethod(); } }
输出结果如下所示:
Error:(3, 8) java: 类 Default.OldInterfaceImplOne从类型
Default.OldInterface 和 Default.AnotherOldInterface 中继承了newDefaultMethod()
的不相关默认值
因为两个接口都有newDefaultMehod的默认实现,jvm也不知道应该在Main方法的调用中用哪个newDefaultMehod方法的默认实现了,产生了二义性,所以报错。
那如果我们在实现类中覆写了newDefaultMehod会不会解决这种二义性呢?
package Default; public class OldInterfaceImplOne implements OldInterface, AnotherOldInterface { @Override public void existingMethod() { System.out.println("Implement existing method version: 1"); } @Override public void anotherExistingMethod() { System.out.println("Another Implement existing method version: 1"); } @Override public void newDefaultMethod() { System.out.println("can default method be correct?"); } }
输出结果:
Implement existing method version: 1 can default method be correct?
可以看到,程序可以正常输出,因为实现类的覆写解决了二义性,也变相证明了default的向下兼容的鲁棒性。
更进一步,你可以在实现类中选择你要用的默认实现。
@Override public void newDefaultMethod() { System.out.println("can default method be correct?"); OldInterface.super.newDefaultMethod(); }
总而言之:
1. default机制允许接口提供一些方法的默认实现。
2. default方法向下兼容。
3. default方法可能在实现类中存在二义性。