我们知道Java语言中一个类只能继承一个父类,但是一个类可以实现多个接口。随着默认方 法在Java 8中引入,有可能出现一个类继承了多个方法而它们使用的却是同样的函数签名。这种 情况下,类会选择使用哪一个函数?在实际情况中,像这样的冲突可能极少发生,但是一旦发生 这样的状况,必须要有一套规则来确定按照什么样的约定处理这些冲突。这一节中,我们会介绍 Java编译器如何解决这种潜在的冲突。我们试图回答像“接下来的代码中,哪一个hello方法是 被C类调用的”这样的问题。注意,接下来的例子主要用于说明容易出问题的场景,并不表示这
些场景在实际开发过程中会经常发生。

public interface A {
    default public void hello(){
        System.out.println( "我是接口A");
    }
}
public interface B  extends A{
    @Override
    default public void hello(){
        System.out.println( "我是接口B");
    }
}
public class C implements A,B {
    public static void main(String... args) { 
        new C().hello();
    }
}

  

 上面会输出什么?

输出是  接口B

说如果类或者父类没有对应的方法,那么就应 该选择提供了最具体实现的接口中的方法。因此,编译器会在接口A和接口B的hello方法之间做
选择。由于B更加具体,所以程序会再次打印输出接口B  运用了下面规则的(2)

现在我们在加一个类 D  

public class D implements A {
    @Override
    public void hello(){
        System.out.println("我是 D");
    }
}

  并对接口c做一些更改  让C 继承D

public class C extends D implements A,B {
    public static void main(String... args) {
        new C().hello();
    }
}

  现在输出的内容是什么

 

答案是 接口D

由于依据规则(1),父类中声明的方法具有更高的优先级,所以程序会打印输出“Hello from D”。

 

 

总结

解决问题的三条规则 如果一个类使用相同的函数签名从多个地方(比如另一个类或接口)继承了方法,通过三条
规则可以进行判断。

(1) 类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优
先级。

(2) 如果无法依据第一条进行判断,那么子接口的优先级更高:函数签名相同时,优先选择
拥有最具体实现的默认方法的接口,即如果B继承了A,那么B就比A更加具体。
(3) 最后,如果还是无法判断,继承了多个接口的类必须通过显式覆盖和调用期望的方法,