次の小さなテスト クラスを検討してください。
import java.util.List;
public abstract class Test {
// CAN modify this constructor interface
public <T extends Runnable & Comparable<T>> Test(List<T> l) {
setList((List<Runnable>)l); // <-- (a) warning
setList(l); // <-- (b) error
}
// CANNOT modify this interface
public abstract void setList(List<Runnable> l);
}
これは私の問題を簡潔に表しています. のコンストラクタのような型T
( と の両方Runnable
である)のオブジェクトを取るジェネリックメソッドを使いたいのですが.Comparable<T>
Test
setList
T
(a)コンパイラは、 ( JLS SE7 §4.6 に従って) where extendsのインスタンスであり、型の消去があるList<Runnable>
場合に、未チェックの変換について警告するのはなぜですか?l
List<T>
T
Runnable
(b)コンパイラは次のエラーを発生させます。
error: method setList in class Test cannot be applied to given types;
setList(l); // <-- compiler error
^
required: List<Runnable>
found: List<T> reason: actual argument List<T> cannot be converted to
List<Runnable> by method invocation conversion
where T is a type-variable:
T extends Runnable,Comparable<T> declared in constructor <T>Test(List<T>)
ここでの私の理解は、おそらくこれは縮小操作と見なされるため、メソッド呼び出しの変換が に変換できなかったということですが、予想どおり、と の両方と交差する可能性があるため、これは直感に反します。T
Runnable
T
Runnable
Comparable<T>
この場合、 T
toのインスタンスの未チェックの変換 (a) に頼る必要がありますか?List<Runnable>
編集
Bhesh が以下で指摘しているように、答えはイエスであることが判明しました。ジェネリック型は Java では不変です。以下を使用できれば、エラー (b) は発生しません。
public abstract void setList(List<? extends Runnable> l);
詳細については、この優れたチュートリアルと、 JLS SE7 §5.1.10のキャプチャ変換に関するこのセクションを参照してください。