メソッドは、質問するタイプの別のメソッドと同じ消去を持っています

メソッドは、質問するタイプの別のメソッドと同じ消去を持っています

同じクラスに次の 2 つのメソッドが存在するのはなぜ不正なのでしょうか?

class Test{
   void add(Set<Integer> ii){}
   void add(Set<String> ss){}
}

私はcompilation error

メソッド add(Set) には、型 Test の別のメソッドと同じ消去 add(Set) があります。

回避策はありますが、javac がなぜこれを好まないのか疑問に思いました。

多くの場合、これら2つの方法のロジックは非常に似ており、1つの方法に置き換えることができることがわかります。

public void add(Set<?> set){}

方法ですが、常にそうであるとは限りません。

constructorsこれらの引数を取る を 2 つ用意したい場合、そのうちの 1 つの名前を変更するだけでは不十分なため、これはさらに面倒ですconstructors

ベストアンサー1

このルールは、生の型をまだ使用しているレガシー コードでの競合を回避することを目的としています。

これがなぜ許可されなかったのか、以下に例を挙げて説明します。JLS から抽出されました。ジェネリックが Java に導入される前に、次のようなコードを書いたとします。

class CollectionConverter {
  List toList(Collection c) {...}
}

次のようにクラスを拡張します。

class Overrider extends CollectionConverter{
  List toList(Collection c) {...}
}

ジェネリックの導入後、ライブラリを更新することにしました。

class CollectionConverter {
  <T> List<T> toList(Collection<T> c) {...}
}

更新する準備ができていないので、Overriderクラスはそのままにしておきます。メソッドを正しくオーバーライドするためにtoList()、言語設計者は、生の型がジェネリック型と「オーバーライド同等」であると判断しました。つまり、メソッド シグネチャはもはやスーパークラスのシグネチャと形式的には等しくありませんが、メソッドは依然としてオーバーライドします。

さて、時間が経ち、クラスを更新する準備ができたと判断しました。しかし、少し失敗してしまい、既存の未加工のtoList()メソッドを編集する代わりに、次のような新しいメソッドを追加してしまいました。

class Overrider extends CollectionConverter {
  @Override
  List toList(Collection c) {...}
  @Override
  <T> List<T> toList(Collection<T> c) {...}
}

生の型のオーバーライド同等性のため、両方のメソッドはメソッドをオーバーライドする有効な形式になっていますtoList(Collection<T>)。ただし、もちろん、コンパイラは単一のメソッドを解決する必要があります。このあいまいさを排除するために、クラスにはオーバーライド同等の複数のメソッド、つまり消去後に同じパラメーター型を持つ複数のメソッドを含めることはできません。

重要なのは、これが生の型を使用する古いコードとの互換性を維持するために設計された言語ルールであるということです。これは、型パラメータの消去に必要な制限ではありません。メソッドの解決はコンパイル時に行われるため、メソッド識別子にジェネリック型を追加するだけで十分でした。

おすすめ記事