默认方法
可以为接口方法提供一个默认实现.必须用default修饰符标记这样一个方法.
public interface Comparable<T>{
default int compareTo(T other){return 0}
}
解决默认方法冲突
如果现在一个接口中将一个方法定义为默认方法,然后又在超类或另一个接口中定义了同样的方法,会发生什么情况?java解决的规则很简单:
- 超类优先.如果超类提供了一个具体方法,同名而且相同参数类型的默认方法会被忽略,以超类的方法为准.
- 接口冲突.如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型(不论是否为默认参数)相同的方法,必须覆盖这个方法来解决冲突
下面看第二条规则,考虑另一个包含getName方法的接口
interface Named{
default String getName(){
return getClass.getName() + "_"+hashCode();
}
}
如果有一个类同时实现了这两个接口会怎样? 其中Person接口也有getName()
class Student implements Person,Named{
...
}
类继承Person和Named接口提供的两个不一致的getName方法.并不是从中选择一个,Java编译器会报告一个错误,让程序员来解决这个二义性.只需要在Student类中提供一个getName方法.在这个方法中,可以选择两个冲突方法中的一个.如下所示
class Student implements Person,Named{
public String getName(){
return Person.getName();
}
}
现在假设Named接口没有为getName提供默认的实现:
interface Named{
String getName();
}
Student类会从Person接口继承默认方法吗?答案是不会,java设计者更强调一致性.两个接口如何冲突并不重要.如果至少有一个接口提供了一个实现,编译器就会报告一个错误,而程序员就必须解决这个二义性.
我们值讨论了两个接口的冲突.现在考虑另外一种情况,一个类扩展了一个超类,同时实现了一个接口,并从超类和接口继承了相同的方法,加入Person是一个类,Student的定义为:
class Student extends Person implements Named{
...
}
在这种情况下,只会考虑超类方法,接口的所有默认方法都会被忽略.这就是类优先.