1. ホーム
  2. java

[解決済み] メソッドは、タイプ内の別のメソッドと同じ消去を持つ

2022-03-24 16:53:19

質問

同じクラスに次の2つのメソッドを持つことは、なぜ不正なのでしょうか?

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

を取得します。 compilation error

メソッド add(Set) は、Test 型の別のメソッドと同じ消去を持つ。

というのも、javacはなぜこのようなことをしないのでしょうか?

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

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

メソッドを使用することができますが、必ずしもそうとは限りません。

を2つ持ちたい場合、これは余計に厄介なことです。 constructors というのも、これらの引数を取る一方の constructors .

解決方法は?

このルールは、生の型をまだ使用しているレガシーコードでの衝突を避けるためのものです。

なぜこれが許されなかったのか、その理由を説明します。 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) {...}
}

raw型のオーバーライドの等価性から、どちらの方法も有効な形で toList(Collection<T>) メソッドを使用します。しかし、当然ながら、コンパイラは単一のメソッドを解決する必要があります。この曖昧さをなくすために、クラスはオーバーライド等価なメソッド、つまり消去後に同じパラメータ型を持つメソッドを複数持つことができないようになっています。

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