-1

次の小さなテスト クラスを検討してください。

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>TestsetListT

(a)コンパイラは、 ( JLS SE7 §4.6 に従って) where extendsのインスタンスであり、型の消去があるList<Runnable>場合に、未チェックの変換について警告するのはなぜですか?lList<T>TRunnable

(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>)

ここでの私の理解は、おそらくこれは縮小操作と見なされるため、メソッド呼び出しの変換が に変換できなかったということですが、予想どおり、と の両方と交差する可能性があるため、これは直感に反します。TRunnableTRunnableComparable<T>

この場合、 Ttoのインスタンスの未チェックの変換 (a) に頼る必要がありますか?List<Runnable>

編集

Bhesh が以下で指摘しているように、答えはイエスであることが判明しました。ジェネリック型は Java では不変です。以下を使用できれば、エラー (b) は発生しません。

public abstract void setList(List<? extends Runnable> l);

詳細については、この優れたチュートリアルと、 JLS SE7 §5.1.10のキャプチャ変換に関するこのセクションを参照してください。

4

1 に答える 1

1

a) Tis-a Runnablebut List<T>is-not-a List<Runnable>. Java ではジェネリック型は不変です。

b) 理由は上記と同じ。Java では、メソッド パラメータも不変です。(注: メソッドの引数は共変です。)


キャストインsetList((List<Runnable>)l);は安全である必要があります。これは、T常に を実装するものになることがわかっているためRunnableです。これは、注釈@SuppressWarnings("unchecked")が存在するタイプの状況です。


それでも、(状況によっては) コンストラクターからオーバーライド可能なメソッドを呼び出していることが問題になる可能性があります。

于 2012-11-01T04:18:11.157 に答える