4

2 つのインターフェイス 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 つの実装しかないことを理解しています。

  1. コンパイラは、throws 句に基づいて、このメソッドが I1 または I2 からのものかどうかを推測しますか? メソッド署名の明確化は必要ですか? (署名には、渡された名前とパラメーターが含まれていることを知っています。)

  2. 両方のインターフェースを実装してから e1 のみをスローする場合、実装するクラスが実際には両方のインターフェースを実装していないため、コンパイラはこれを許可しますか? それはダイヤモンド構造の問題を引き起こしますか?

  3. throws 句 e1 と 2 回目の e2 で同じメソッドを実装する必要がありますか? これを試したとき、コンパイラはメソッドが重複していることを教えてくれました。

  4. 最初に I1 を実装すると、それが I1 のメソッドであることが示され、最初に I2 を記述すると、その I2 のメソッドであることが示されます。なぜそうなのか説明せよ。

4

2 に答える 2

7

インターフェイスはコントラクトを定義します。インターフェイスがメソッドを定義する場合

void foo() throws SomeException;

次に、それは次のように述べています:すべての実装クラスにはメソッド foo が必要であり、void を返し、引数を取らず、 SomeException をスローすることは許可されていますが、他のタイプのチェックされた例外は許可されていません。

もちろん、実装メソッドは、インターフェースメソッドの契約に違反しないため、例外をまったくスローしないことを選択できます。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 の間に継承がない場合、両方のインターフェイスを実装する唯一の方法は、例外をスローしないメソッドを持つことです。それが 2 つの契約を満たす唯一の可能性です。

于 2013-11-12T15:47:07.400 に答える
1

オーバーライドに関しては、メソッドのパラメータ タイプのみが考慮されます(8.4.2)。戻り値の型とスロー型は、後で別の手順(8.4.8.3)でチェックされます。

クラスは、オーバーライドと同等のシグネチャを持つ複数のメソッドを継承できます。(8.4.8.4)問題ありません。あなたの場合、2 つのメソッドが継承され、両方が 1 つのメソッドによってオーバーライドされます。

私の IDE IntelliJ は、メソッドが 2 つのスーパー インターフェイスで 2 つのメソッドをオーバーライドすることを正しく報告します。

Java 7 以前では、ひし形の問題はありません。ただし、Java 8 以降では、インターフェイス メソッドに実装を含めることができます。したがって、クラスが 2 つのインターフェイスから 2 つのメソッドを継承する場合、ひし形の問題が発生する可能性があります。そのようなあいまいさが存在する場合、Javac はコードを拒否することがあります。(あいまいさを解消する方法があります)。

于 2013-11-12T16:33:51.470 に答える