それはあなたが何をする必要があるかに依存します。次のようなことをしたい場合は、有界型パラメーターを使用する必要があります。
public <T extends Shape> void addIfPretty(List<T> shapes, T shape) {
if (shape.isPretty()) {
shapes.add(shape);
}
}
ここでは、持っているList<T> shapes
とT shape
、それゆえ我々は安全にすることができますshapes.add(shape)
。宣言されている場合はList<? extends Shape>
、安全に行うことはできませんadd
(とが存在する可能性があるList<Square>
ためCircle
)。
したがって、制限付き型パラメーターに名前を付けることで、ジェネリックメソッドの他の場所でそれを使用するオプションがあります。もちろん、この情報は必ずしも必要ではないため、タイプ(たとえば、drawAll
)についてそれほど詳しく知る必要がない場合は、ワイルドカードだけで十分です。
境界タイプパラメータを再度参照しない場合でも、複数の境界がある場合は、境界タイプパラメータが必要です。これは、AngelikaLangerのJavaGenericsFAQからの引用です。
ワイルドカードバインドとタイプパラメータバインドの違いは何ですか?
ワイルドカードには1つの境界しかありませんが、型パラメーターには複数の境界を含めることができます。ワイルドカードには下限または上限を設定できますが、型パラメーターの下限などはありません。
ワイルドカードの境界と型パラメーターの境界は、どちらも境界と呼ばれ、構文が部分的に類似しているため、混同されることがよくあります。[…]
構文:
type parameter bound T extends Class & Interface1 & … & InterfaceN
wildcard bound
upper bound ? extends SuperType
lower bound ? super SubType
ワイルドカードには、下限または上限のいずれかの境界を1つだけ含めることができます。ワイルドカード境界のリストは許可されていません。
対照的に、型パラメーターにはいくつかの境界がありますが、型パラメーターの下限などはありません。
効果的なJava2nd Edition、アイテム28からの引用:APIの柔軟性を高めるために、制限付きワイルドカードを使用します。
最大限の柔軟性を得るには、プロデューサーまたはコンシューマーを表す入力パラメーターにワイルドカードタイプを使用します。[…] PECSは生産extends
者super
- 、消費者-の略です-[…]
戻り値の型としてワイルドカード型を使用しないでください。ユーザーに追加の柔軟性を提供するのではなく、クライアントコードでワイルドカードタイプを使用するように強制します。適切に使用されると、ワイルドカードタイプはクラスのユーザーにはほとんど見えなくなります。それらは、メソッドに、受け入れるべきパラメーターを受け入れさせ、拒否すべきパラメーターを拒否させます。クラスのユーザーがワイルドカードタイプについて考える必要がある場合は、クラスのAPIに問題がある可能性があります。
PECSの原則を適用するaddIfPretty
と、次のように記述して、例に戻り、より柔軟にすることができます。
public <T extends Shape> void addIfPretty(List<? super T> list, T shape) { … }
今、私たちはできるaddIfPretty
、と言うCircle
には、List<Object>
。これは明らかにタイプセーフですが、元の宣言はそれを可能にするほど柔軟ではありませんでした。
関連する質問
概要
- 制限付きタイプのパラメーター/ワイルドカードを使用してください。APIの柔軟性が向上します。
- 型に複数のパラメーターが必要な場合は、制限付き型パラメーターを使用する以外に選択肢はありません。
- タイプに下限が必要な場合は、制限付きワイルドカードを使用する以外に選択肢はありません。
- 「生産者」には上限があり、「消費者」には下限があります
- 戻り値の型にワイルドカードを使用しないでください