2

次のインターフェースと実装クラスがあるとしましょう。

interface Foo<FooType extends Foo<FooType>> {
    FooType copy();
}

class Bar implements Foo<Bar> {
    public Bar copy() {
        return new Bar();
    }       
}

私がこれをやろうとすると:

public <FooType extends Foo<FooType>> FooType getFoo() {
    return new Bar();
}

「タイプの不一致:BarからFooTypeに変換できません」というコンパイルエラーが発生します。なんで?

次のように関数を書き直すことで、これを「修正」できます。

@SuppressWarnings("unchecked")
public <FooType extends Foo<FooType>> FooType getFoo() {
    return (FooType) new Bar();
}

しかし、私がこのような関数を持っているとしましょう:

public <FooType extends Foo<FooType>> void printFoo(FooType foo) {
    System.out.println(foo.toString());
}

私がこれをやろうとすると:

printFoo(getFoo());

次のコンパイルエラーが発生します。

Bound mismatch: The generic method printFoo(FooType) is not applicable 
for the arguments (Foo<Foo<FooType>>). The inferred type Foo<Foo<FooType>> 
is not a valid substitute for the bounded parameter <FooType extends Foo<FooType>>

ワット?getFoo()の戻り型は、printFoo()の引数型と文字通り同じです。

これらのバグですか、それとも何かが足りませんか?

4

3 に答える 3

3

問題は、それFooTypeだけではない可能性があるということBarです。のインスタンスを返すことができますFooType

class NotBar implements Foo<NotBar> {

 obj.<NotBar>getFoo();

ここで、の実際の引数はFooTypeですNotBar

于 2012-11-29T19:45:01.383 に答える
0

問題はこれであり、あなたが宣言するメソッドで:

public <FooType extends Foo<FooType>> FooType doGetFoo() 

これは、指定したジェネリックの型を取り戻す必要があることを示すジェネリックメソッドです。たとえば、Batextendsの呼び出しがFoo<Bat>あり、それを呼び出すinstance.<Bat>doGetFoo()と、のインスタンスを返す必要があります。Bat代わりに、withのインスタンスを返すようにハードコーディングされていますBarが、必ずしもジェネリックで指定されたクラスのインスタンスであるとは限りません。以下のようにジェネリックを削除すると、問題がないはずです。

public Foo<?> doGetFoo(){
    return new Bar();
}
于 2012-11-29T19:50:02.323 に答える
0

とった!このバージョンの質問に答えてくれたメリトンに感謝します。

実行時のinstanceofチェックをコンパイル時のジェネリックス検証に置き換える方法

私はprintFoo(getFoo())これを行うことによって-partを通してコンパイラをベビーステップする必要があります:

public <FooType extends Foo<FooType>> void doPrint() {
    FooType foo = getFoo();
    printFoo(foo);
}

代わりにそれを呼び出しますdoPrint()

その後、すべてが正常に動作します。

それで、「なぜ?」とはいえ、私は推測します。真ん中には私の理解不足があったかもしれません(その部分を片付けてくれたBheshに感謝します)、「WAT?」これは実際に機能するはずなので、最後に正当化されました...たとえば、上記のコードで「foo」の変数定義をインライン化することは、何らかの理由でOKではありません...

于 2012-11-30T00:45:46.117 に答える