基本型を拡張するジェネリックを操作する 2 つの形式を次に示します。
public abstract <T extends Runnable> BlockingQueue<T> getQueueA();
public abstract BlockingQueue<? extends Runnable> getQueueB();
理解できない。違いはなんですか?どちらのメソッドも、Runnable を拡張するオブジェクトの同じ BlockingQueue を返すようです。
基本型を拡張するジェネリックを操作する 2 つの形式を次に示します。
public abstract <T extends Runnable> BlockingQueue<T> getQueueA();
public abstract BlockingQueue<? extends Runnable> getQueueB();
理解できない。違いはなんですか?どちらのメソッドも、Runnable を拡張するオブジェクトの同じ BlockingQueue を返すようです。
BlockingQueue<Thread> threads = thing.getQueueA(); // works
BlockingQueue<Thread> threads = thing.getQueueB(); // does not work
物事の反対側:
@Override public <T extends Runnable> BlockingQueue<T> getQueueA() {
return new ArrayBlockQueue<Thread>(); // no worky
}
@Override public BlockingQueue<? extends Runnable> getQueueB() {
return new ArrayBlockQueue<Thread>(); // works
}
どちらも Runnable を拡張する型のキューを返しますが、違いは、最初のバージョンは型指定されたメソッドであり、その型T
はメソッド内およびコンパイラで使用できるため、メソッドが呼び出されたときに型を推測できることです。
2 番目のバージョンには、これらの利点はありません。タイプが不明なキューを返すだけで、Runnable を拡張します。