今日、私は次の問題に遭遇しました。セットアップを検討してください:
interface A {
void foo();
}
interface B {
void bar();
}
class Impl implements A,B {
public void foo() { }
public void bar() { }
}
class Usage {
void worksAsParameter(){
acceptIt(new Impl());
}
<T extends A & B> void acceptIt(T foo){
}
<T extends A & B> T returnIt(){
return new Impl(); // <-- Compile error
}
}
コードは、マークされている最後のステートメントを除いてコンパイルされます。エクリプスは私にerror: Type mismatch: cannot convert from Impl to T
私の質問は次のとおりです:パラメータとして指定された場合にImpl
代入可能であるのはなぜですかT
(に示されてworksAsParameter
いますT
が、戻り値null
の型T
である場合はそうではありImpl
ません)。
この質問は、このSOの質問と似ていますが、同じではないことに注意してください。
編集:タイプミスを修正しました。
=== まとめ ===
ジェネリックな戻り値の型がどのように機能するかを誤解していたようです。私はそれについての私の新しい理解を書き込もうとします。
問題を見てみましょう:
<T extends A & B> T returnIt(){
return new Impl(); // <-- Compile error
}
私の最初の仮定は、実装クラス (この場合は ) が、拡張する必要があるという制限付きUsage
の具体的な型を決定し、. どうやら、何が何であるかを決定し、に割り当て可能な値を提供する必要があるのは、呼び出し元/呼び出しサイトです。ただし、コンパイル時の取引のみであるため、(何にでも代入可能であるため) を除いてそのような値を指定することはできません。私の知る限り、これは、フォームのコードは次の値しか返せないことを意味します。T
A
B
T
Usage
T
T
null
null
<T extends A> T returnIt(){
return x; // <-- Compile error
}
うまくいけば、別の設定でより便利になるかなり直観的でない機能。ありがとうピーター!