<T>
、<T>
、および<?>
は完全に異なります。
class X<T>
という名前の型パラメーター (プレースホルダー) を持つジェネリック クラスを宣言しますT
。そのクラス内でT
は、有効な型です。
X<T> something
変数またはフィールドの宣言です。ジェネリック型の変数を宣言し、ジェネリック パラメータの値を指定します。
X<?> something
変数またはフィールドの宣言でもあります。ジェネリック型の変数を宣言していますが、ジェネリック パラメータの値を指定していません。
ジェネリック クラスを作成する場合、必要に応じてジェネリック パラメーターに制約を追加し、ユーザーがそのクラスのインスタンス (変数) を宣言するときに許可される型を指定できます。
したがって、class X<T extends SomeClass>
柔軟性の低い型パラメーターを持つジェネリック クラスを作成します。
ジェネリック クラス (例: private Collection<String> myStrings
) を使用する場合、明らかに、ジェネリック パラメータの値に制約を指定することはできません (既に実際の値を指定しているため)。
したがって、private Collection<String extends Comparable> myStrings
意味がありません。
ワイルドカード (またはバインドされていない) パラメーター (例: )を含むジェネリック クラスを使用する場合private Collection<?> myThingies
、任意で、パラメーターが何であれ、制約を指定できます。これにより、ジェネリック パラメーターの (不明な) 値について推測することができます。
したがって、private Collection<? extends Runnable> myRunners
は型が を実装することを保証する未知の型のコレクションですRunnable
。.run()
したがって、コレクション内のものを呼び出すことができます。
ただし、コレクションが実際に保持する必要がある型がわからないため、コレクションに何も入れることはできません。