建议何时执行:
public <E> boolean hasPropertyX(List<E extends User> alist);
与
public boolean hasPropertyX(List<? extends User> alist);
看起来它们的效果也一样。
答案 0 :(得分:4)
没有类型返回值,我能想到的唯一区别是在方法调用期间显式输入第一种声明方式。
例如,您在类型类C<K extends String>
List<V extends String> input = ...;
boolean var = obj.hasProperty<K>(input);
会引发编译错误。但是为什么有人想要这样做......
很好的问题,即使答案很可能两者都是一样的。
答案 1 :(得分:2)
明确地将通用类型命名为E
而不是?
具有这些用途(据我所知):
0)将返回类型绑定到参数类型的某些部分 - 例如:
public <E> E getSomeElement(List<E> lst) { ... }
// ^ If we don't name the argument type as having E,
// then we can't specify the return type as being E
1)将参数类型的某些部分绑定到封闭类型的某些部分:
class Storage<E> {
E item;
public void replace(Storage<E> st) { item = st.item; }
// ^ This wouldn't work if we wrote Storage<?> instead
}
2)绑定参数类型的一些组合,返回类型和封闭类型(参见#0和#1)。
如果我们不关心实际类型,我们可以使用匿名类型名称?
。这是一个基本的例子:
boolean allEqual(List<?> lst, Object y) {
for (Object x : lst) { // Any reference can be stored as Object
if (!y.equals(x)) // equals takes an Object
return false;
}
return true;
}
// ^ We could also rewrite this example with List<E> and "E x".
另一个例子:
int intSum(List<? extends Number> lst) {
int sum = 0;
for (Number x : lst) // We only care that the list element is a Number
sum += x.intValue();
return sum;
}
// ^ We could also rewrite with List<E extends Number> and "E x".
替代阅读:http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
答案 2 :(得分:2)
我想在那个特定的例子中,它们在类型检查方面都以相同的方式有效地工作。但是,如果将泛型类型扩展为需要某个类的基类或超类,则它可能很有用。 e.g。
public <E extends User> boolean hasPropertyX(List<E> alist);
这至少强制您接收User
的一些子类。
修改强>
您可以使用通配符来实现相同的目标:
public boolean hasPropertyX(List<? extends User> alist);
但是,如果您想要将泛型用于多个参数,那么这将无效:
public <E extends Automobile> void crashAutos(List<E> list1, List<E> list2);
这会对两个参数强制执行泛型类型,而以下代码不会强制两个列表包含相同的类型:
public void crashAutos(List<? extends Automobile> list1, List<? extends Automobile> list2);
我可以使用Automobile
类的两个不同的子类调用该方法:
List<Car> cars = ...
List<Truck> trucks = ...
crashAutos(cars, trucks);
使用泛型对两个参数强制执行相同的类型。
答案 3 :(得分:2)
泛型和通配符未知类型之间的差异:
相关问题:
答案 4 :(得分:1)
当您只需要从列表中检索时使用? extends
:
User getElement(List<? extends User> list, int i) {
return list.get(i);
}
只需添加到列表时使用? super
:
void addElement(List<? super User> list, User u) {
list.add(u);
}
当两者需要检索并添加:
时,请使用E extends
<E extends User> void swapElements(List<E> list, int i, int j) {
E temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
? extends User
:我们不知道列表的确切类型,但我们可以从中检索User
。? super User
:我们不知道列表的确切类型,但我们可以在其中添加User
。E extends User
:我们不一定知道列表的确切类型,但它符合以下限制:
E
。E
至少是User
。E
并将E
放入列表中。另见: