阐明多重继承的概念:钻石结构问题是否会发生?

时间:2013-11-12 15:34:06

标签: java interface multiple-inheritance diamond-problem

假设您有两个接口I1和I2,这两个接口具有相同的方法

1)public int add(int a) throws exception e1    //(Interface 1)

2)public int add(int a) throws exception e2    //(Interface 2)

现在一个类实现了I1和I2。

@override
public int add(int a) exception e1
{
//adding operation
}

注意:我知道如果你实现多个具有相同方法的接口,那么实现类中只有一个实现。

  1. 编译器是否根据throws子句推断此方法是来自I1还是I2?是否需要方法签名澄清? (我知道签名包括传递的名称和参数。)

  2. 如果我们已经实现了两个接口,然后我们只抛出e1,那么编译器会允许这个,因为实现类并没有真正实现这两个接口?它会导致钻石结构问题吗?

  3. 我们是否需要使用throws子句e1和第二次e2实现相同的方法?当我尝试这个时,编译器告诉我我有重复的方法。

  4. 如果我们首先实现I1,那么它表示它是I1的方法,如果我们首先编写I2,那么它会说它是I2的方法。解释为什么会这样。

2 个答案:

答案 0 :(得分:7)

接口定义合同。如果接口定义了方法

void foo() throws SomeException;

然后它说:所有实现类必须有一个方法foo,返回void,不接受任何参数,并允许抛出SomeException 但没有其他类型的checkd异常

实现方法当然可以选择不抛出任何异常,因为它不会违反接口方法的约定。 throws表示:在某些情况下,此方法可能会抛出此异常。

所以,一个声明为

的方法
public void foo();
实现类中的

对上面定义的接口有效。

所以,在你的例子中,

public int add(int a) throws Exception1

是一个有效的方法声明,可以覆盖

int add(int a) throws Exception1

有效
int add(int a) throws Exception2

(当然,除非Exception1是Exception2的子类)。

唯一的方法是,如果在Excption1和Exception2之间没有继承,那么实现这两个接口的方法就是不要抛出任何异常。这是填写这两份合约的唯一可能性。

答案 1 :(得分:1)

关于覆盖,只考虑方法的参数类型(8.4.2);稍后将在单独的步骤(8.4.8.3)中检查返回类型和投掷类型。

类可以使用override-equivalent继承多个方法 签名。 (8.4.8.4)那里没有问题。在您的情况下,继承了两个方法,然后两个方法都被一个方法覆盖。

我的IDE IntelliJ正确报告该方法覆盖了两个超级接口中的两个方法。

在Java 7及更早版本中,没有钻石问题。但是从Java 8开始,接口方法就可以实现了!因此,当类从两个接口继承两个方法时,可能会发生菱形问题。如果存在这种歧义,Javac可能会拒绝该代码。 (有一些方法可以消除歧义)。