[英]Generic vs wildcard unknown types
什么时候建议做:
public <E> boolean hasPropertyX(List<E extends User> alist);
与
public boolean hasPropertyX(List<? extends User> alist);
看起来它们的效果也一样好。
没有类型返回值,我能想到的唯一区别是在方法调用期间显式输入第一种声明方式。
例如,您在类型C<K extends String>
中使用它
List<V extends String> input = ...;
boolean var = obj.hasProperty<K>(input);
会引发编译错误。 但是为什么有人想要这样做......
很好的问题,即使答案很可能两者都是一样的。
明确地将泛型类型命名为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
我想在那个特定的例子中,它们在类型检查方面都以相同的方式有效地工作。 但是,如果将泛型类型扩展为需要某个类的基类或超类,则它可能很有用。 例如
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);
而使用泛型对两个参数强制执行相同的类型。
用? extends
当您只需要从List中检索时? extends
:
User getElement(List<? extends User> list, int i) {
return list.get(i);
}
用? super
当你只需要添加到List时? 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
? extends User
:我们不知道List的确切类型,但我们可以从中检索User
。 ? super User
? super User
:我们不知道列表的确切类型,但我们可以将User
放入其中。 E extends User
:我们不一定知道List的确切类型,但它符合约束,例如:
E
E
至少是User
。 E
并将E
放入List中。 也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.