3

次のようなコードがあります。

public class Main {

    private static abstract class Bar {}

    private static class SubBar extends Bar {}

    private static abstract class Baz<T extends Bar> {

        private T t;

        public void setT(T t) {
            this.t = t;
        }

    }

    private static class SubBaz extends Baz<SubBar> {}


    private void foo(Baz<? extends Bar> baz, Bar bar) {
        baz.setT(bar);
    }
 }

その結果、エラーが発生します。

error: method setT in class Baz<T> cannot be applied to given types;
required: CAP#1
found: Bar
reason: actual argument Bar cannot be converted to CAP#1 by method invocation conversion
where T is a type-variable:
T extends Bar declared in class Baz
where CAP#1 is a fresh type-variable:
CAP#1 extends Bar from capture of ? extends Bar

理由がわかりません。メソッド setT は Bar を拡張するものを受け入れる必要があり、Bar クラスのものを渡しています。

4

2 に答える 2

4

メソッド setT は Bar を拡張するものを受け入れる必要があり、Bar クラスのものを渡しています。

それがまさに問題です。<? extends Bar>「未知の型Barまたはそのサブクラス」を意味します。どの型かわからないため、実際には、パラメーターを使用setT()しない限り、そのコンテキストで呼び出すことはできません。null

これは期待どおりに機能します。

private void foo(Baz<Bar> baz, Bar bar) {
    baz.setT(bar);
}

Stackoverflow には、この質問のバリエーションが何百もあると思います。ほとんどすべてのプログラマーは、最初は?ワイルドカードの目的を誤解し、間違って使用しているようです。

そのユーティリティは、Barクラスにpublic T getT()メソッドがある状況にあります。type の変数はとBaz<? extends Bar>の両方のオブジェクトを保持でき、それを呼び出して(または何らかのサブクラス) であり、そのように使用できるものを取得できます。Baz<Bar>Baz<SubBar>getT()Bar

于 2012-10-04T18:47:36.060 に答える
0

あなたがやろうとしていることは、タイプセーフではありません。あなたが持っていた場合:

private static class OtherSubBar extends Bar {}

次に、次のことができます。

Baz<SubBar> baz = new Baz<SubBar>();
foo(baz, new OtherSubBar());
于 2012-10-04T18:47:16.607 に答える