1、接口的默认方法
接口的默认方法是指在接口中由default修饰的方法,不同于普通的接口方法的是,该方法有具体的方法体。
2、和抽象类的区别
接口的方法既然有默认的方法体,这和抽象类就有了一定的相似之处。但还是有区别的:
1、抽象类是类,子类继承抽象类只能继承一个抽象类,而对于接口,则可以实现多个接口。
2、抽象类可以声明和使用字段;接口则不能,接口只能创静态的final常量。
当然还有其它区别,这里就不列举了,网上有很多总结。总之,Java8中接口的方法可以有默认的方法体之后,接口和抽象类还是有很多区别的,并且各自的使用场景也不同。
3、继承多个接口时,接口默认方法的冲突问题
由于子类可以实现多个接口,并且子类可以继承一个父类,这些父类和接口中有相同名称的默认方法,这时候就会有冲突问题。解决这些冲突问题主要有3条原则:
1、父类的优先级最高,例如:类C继承类B,并实现接口A,当类B和接口A有相同名称的方法时,类C调用继承类B的方法。
2、当不满足上面一条时,比如子类没有继承父类,或父类没有与其实现的接口有相同名称的方法,且子类实现的多个接口之间有继承的关系那么子类将默认继承子接口的默认方法。例如:类C实现接口B和接口A,当接口B继承接口A,且具有接口B和接口A有相同名称的方法时,类C默认调用接口B的方法。
3、当不满足上两条时,则子类必须通过显式覆盖和调用期望的方法, 显式地选择使用哪一个默认方法的实现。
4、相关实例
实例1
public class ClassB {
public void hi(){
System.out.println("classB say hi!");
}
}
public interface InterfaceA {
default void hi(){
System.out.println("interfaceA say hi!");
}
}
public class ClassC extends ClassB implements InterfaceA{
public static void main(String[] args){
ClassC classC = new ClassC();
classC.hi();
}
}
输出结果
classB say hi!
由此可见ClassC的实例调用hi()方法,调用的是ClassB的hi()方法。
实例2
public interface InterfaceB extends InterfaceA{
default void hi(){
System.out.println("interfaceB say hi!");
}
}
public interface InterfaceA {
default void hi(){
System.out.println("interfaceA say hi!");
}
}
public class ClassC implements InterfaceA,InterfaceB{
public static void main(String[] args){
ClassC classC = new ClassC();
classC.hi();
}
}
输出结果
interfaceB say hi!
由此可见ClassC的实例调用hi()方法,调用的是InterfaceB的hi()方法。
实例3
public interface InterfaceB {
default void hi(){
System.out.println("interfaceB say hi!");
}
}
public interface InterfaceA {
default void hi(){
System.out.println("interfaceA say hi!");
}
}
public class ClassC implements InterfaceA,InterfaceB{
public static void main(String[] args){
ClassC classC = new ClassC();
classC.hi();
}
}
这时候编译会不通过,因为编译器不知道ClassC该调用那个接口的hi()方法。
实例3(改)
将ClassC的代码改成下面这样
public class ClassC implements InterfaceA,InterfaceB{
@Override
public void hi() {
InterfaceB.super.hi();
}
public static void main(String[] args){
ClassC classC = new ClassC();
classC.hi();
}
}
输出结果
interfaceB say hi!
ClassC中显式地调用了InterfaceB的hi()方法
实例4
public interface InterfaceA {
default void hi(){
System.out.println("interfaceA say hi!");
}
}
public interface InterfaceB extends InterfaceA{
default void hi(){
System.out.println("interfaceB say hi!");
}
}
public class ClassD implements InterfaceA {
}
public class ClassC extends ClassD implements InterfaceA,InterfaceB{
public static void main(String[] args){
ClassC classC = new ClassC();
classC.hi();
}
}
输出结果
interfaceB say hi!
因为InterfaceB里面有更具体的方法实现体所以ClassC的实例调用InterfaceB的hi()方法
实例4(改)
将ClassD改成下面这样
public class ClassD implements InterfaceA {
@Override
public void hi() {
System.out.println("classD say hi!");
}
}
输出结果
classD say hi!
类的具体方法实现优先级高于接口,所以ClassC的实例调用ClassD的hi()方法