3

在 Java 中,一个类只能扩展一个父类,但可以实现多个接口。随着在 Java 8 接口中引入默认方法,一个类可能会通过实现具有相同默认方法的 2 个接口来继承多个具有相同签名的方法 这可能会像 C++ 中一样产生菱形问题

下面代码中的示例输出

new C().hello(); is 

这是第二个

   public interface First {

    default void hello(){
        System.out.println("This is First");
    }
}

 public interface Second extends First {

    default void hello(){
        System.out.println("This is Second");
    }
}

  public class MyClass implements First,Second {

    public static void main(String[] args) {
        new MyClass().hello();
    }
}

Java用来解决钻石问题的解决规则是什么?一个简单的答案,比如谁优先,什么时候会很棒。

4

4 回答 4

5

以下是当一个类从多个地方(另一个类或接口)继承具有相同签名的方法时要遵循的规则:

  • 班级总是赢。类或超类中的方法声明优先于任何默认方法声明。
  • 否则,子接口获胜:选择最具体的默认提供接口中具有相同签名的方法。(例如,在您的情况下,来自 Second 接口的方法应作为 Second extends First 运行)。
  • 最后,如果选择仍然不明确,则从多个接口继承的类必须通过重写并显式调用所需方法来显式选择要使用的默认方法实现。
于 2017-02-14T10:02:36.070 回答
4

Oracle 教程对此进行了非常详细的解释。

您基本上已经从 First 接口覆盖了您的方法,并选择了最具体的接口方法。

于 2017-02-14T10:01:16.207 回答
2

实现两个声明相同默认方法的接口会导致编译错误:

MyClass inherits unrelated defaults for sayHi() from types InterfaceA and InterfaceB 

所以没有钻石问题;)

为了解决这个问题,您可以覆盖实现类中的方法并在那里实现它或遵循正确的接口。

在您的情况下,它看起来像这样(如果您想使用 Interface 的方法First):

 public class MyClass implements First,Second {
     public void hello() {
         First.super.hello();
     }
 }
于 2017-02-14T09:55:10.100 回答
2

您的代码段不是菱形问题,因为 interface second 首先扩展了 interface 并覆盖了方法 hello。

如果不扩展接口,编译器会引发错误

Duplicate default methods named hello with the parameters () and () are inherited from the types Second and First
于 2017-02-14T09:50:29.600 回答