6

次のコードで発生する名前衝突エラーを理解しようとしています。

import java.util.*;
import javax.swing.*;

class Foo<R extends Number> {
    public void doSomething(Number n, Map<String, JComponent> comps) {
    }
}

class Bar extends Foo {
    public void doSomething(Number n, Map<String, JComponent> comps) {
    }
}

エラーメッセージ:

エラー: 名前の衝突: doSomething(Number,Map<String,JComponent>)inBardoSomething(Number,Map<String,JComponent>)inFooの消去は同じですが、どちらも他方をオーバーライドしません

からジェネリック型を削除するか、宣言を;Fooに変更することで修正できることはわかっています。私が知りたいのは、特定のケースでこのエラーが発生する理由ですが、各メソッドからパラメーターを削除すると消えることです。タイプ eraserについていくつか読んだことがありますが、ジェネリックの有無にかかわらず両方のメソッドが同じ消去を行う必要があるため、どちらの場合でも有効なオーバーライドになるように見えます。(ジェネリック パラメータをまだどこでも使用していないことに注意してください。そのため、非常に驚​​いています。)Barclass Bar extends Foo<Integer>comps

以前にジェネリック型を親クラスに追加したことは知っていますが、サブクラスに関する警告のみが表示され、エラーは表示されませんでした。誰でもこのシナリオを説明できますか?

4

1 に答える 1

6

Luiggi のコメントは正しいです。これは生の型の結果です。

クラスのスーパータイプは生のタイプの場合があります。クラスのメンバー アクセスは通常どおりに処理され、スーパータイプのメンバー アクセスは生の型の場合と同様に処理されます。クラスのコンストラクターでは、super への呼び出しは生の型に対するメソッド呼び出しとして扱われます。

これは、スーパータイプ メソッドを呼び出すときだけでなく、オーバーライドするときにも適用されます。

たとえば、次のようにします。

class Bar extends Foo {
    public Bar() {
        doSomething(1, new HashMap<Number, String>());
    }
}

HashMap<Number, String>に割り当て可能な型ではありませんが、コンパイルされることがわかりMap<String, JComponent>ます。

Cスーパークラスまたはスーパーインターフェースから継承されていない生の型のコンストラクタ (§8.8)、インスタンス メソッド (§8.4、§9.4)、または非静的フィールド (§8.3) の型は、対応する生の型です。に対応するジェネリック宣言での型の消去C

C(私たちの場合は であることに注意してくださいBar。)

メソッドをオーバーライドしようとすると、同じことが起こります。Foo#doSomething(..)メソッドをオーバーライドしようとすると、Barクラスは実際に次のように宣言されているのを見ています

public void doSomething(Number n, Map comps) {
}

つまり、型パラメーターのすべての使用法が消去されます。したがって、メソッドを宣言しようとしています

public void doSomething(Number n, Map<String, JComponent> comps) {
}

サブタイプのBar実際には、オーバーライドではなく、オーバーロードの試みです。そして、これは型消去のために失敗します。で確認できる適切なオーバーライドは次のとおり@Overrideです。

public void doSomething(Number n, Map comps) {
}

参考文献:

于 2014-12-01T15:40:13.773 に答える