这取决于你需要做什么。如果要执行如下操作,则需要使用有界类型参数:
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
即使您不再引用有界类型参数,如果有多个边界,则仍然需要有界类型参数。这是Angelika Langer的Java Generics FAQ中的一句话
通配符绑定和类型参数绑定之间有什么区别?
一个通配符只能有一个边界,而一个类型参数可以有多个边界。通配符可以具有下限或上限,而类型参数没有下限。
通配符边界和类型参数边界经常被混淆,因为它们都被称为边界,并且部分具有相似的语法。[...]
语法:
type parameter bound T extends Class & Interface1 & … & InterfaceN
wildcard bound
upper bound ? extends SuperType
lower bound ? super SubType
通配符只能有一个边界,可以是下限,也可以是上限。不允许使用通配符边界列表。
在 constrast 中,类型参数可以有多个边界,但类型参数没有下限。
引自 Effective Java 2nd Edition, Item 28:使用有界通配符来提高 API 的灵活性:
为了获得最大的灵活性,请对表示生产者或使用者的输入参数使用通配符类型。[...]PECS代表生产者,消费者 [...]extends
super
不要使用通配符类型作为返回类型。它不会为用户提供额外的灵活性,而是会强制他们在客户端代码中使用通配符类型。如果使用得当,通配符类型对类的用户几乎不可见。它们使方法接受它们应该接受的参数,并拒绝那些它们应该拒绝的参数。如果类的用户必须考虑通配符类型,则类的 API 可能存在问题。
应用PECS原则,我们现在可以回到我们的示例,并通过编写以下内容使其更加灵活:addIfPretty
public <T extends Shape> void addIfPretty(List<? super T> list, T shape) { … }
现在我们可以,比如说,a ,到 a 。这显然是类型安全的,但我们最初的声明不够灵活,无法允许它。addIfPretty
Circle
List<Object>
相关问题
总结
- 使用有界类型参数/通配符,它们可以提高API的灵活性
- 如果类型需要多个参数,则别无选择,只能使用有界类型参数
- 如果类型需要下限,则别无选择,只能使用有界通配符
- “生产者”有上限,“消费者”有下限
- 不要在返回类型中使用通配符