このルールは、未加工の型をまだ使用しているレガシーコードの競合を回避することを目的としています。
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()
言語の設計者は、メソッドを正しくオーバーライドするために、生の型がすべてのジェネリック型と「オーバーライド等価」であると判断しました。つまり、メソッドのシグネチャは正式には私のスーパークラスのシグネチャと等しくなくなりましたが、メソッドはオーバーライドされます。
これで時間が経過し、クラスを更新する準備ができたと判断しました。しかし、少し台無しにして、既存のraw toList()
メソッドを編集する代わりに、次のような新しいメソッドを追加します。
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
生の型は同等であるため、両方のメソッドはメソッドをオーバーライドする有効な形式になっていますtoList(Collection<T>)
。しかし、もちろん、コンパイラーは単一のメソッドを解決する必要があります。このあいまいさをなくすために、クラスはオーバーライドと同等の複数のメソッドを持つことはできません。つまり、消去後に同じパラメーター型を持つ複数のメソッドがあります。
重要なのは、これが生の型を使用して古いコードとの互換性を維持するように設計された言語規則であることです。これは、型パラメーターの消去によって要求される制限ではありません。メソッドの解決はコンパイル時に行われるため、ジェネリック型をメソッド識別子に追加するだけで十分です。