我有一个关于在Java泛型类型中使用通配符的问题:List<? extends Set>和List<T extends Set>之间的基本区别是什么?我什么时候可以使用这两种方法?
发布于 2011-06-08 21:41:55
有两个原因:
避免不必要的强制转换的:
对于这样的情况,您必须使用T变体:
public <T extends Set> T firstOf(List<T> l) {
return l.get(0);
}对于?,这将变成:
public Set firstOf2(List<? extends Set> l) {
return l.get(0);
}...which不会向firstOf方法的调用者提供相同数量的信息。第一个版本允许调用者这样做:
SubSet first = firstOf(listOfSubSet);而在第二个版本中,您必须使用强制转换来使其编译:
SubSet first = (SubSet)firstOf(listOfSubSet);强制匹配参数类型的:
public <T extends Set> boolean compareSets(List<T> a, List<T> b) {
boolean same = true;
for(T at : a) {
for (T bt: b) {
same &= at.equals(bt);
}
}
return same;
}对于这一点,使用?而不是T没有直接的等价物。请注意,由于Java的单分派,在上面的版本中,编译器将调用at的equals(T)方法,该方法很可能与at的equals(Set)或equals(Object)方法不同。
发布于 2011-06-08 21:39:14
这里的不同之处在于,在第二个版本中,您有一个类型变量T,它引用List包含的Set的特定子类型。在需要确保其他类型与列表中包含的类型相同的情况下,需要使用它。下面是几个简单的例子:
// want to ensure that the method returns the same type contained in the list
public <T extends Set> T something(List<T> list) {
...
}
// want to ensure both lists contain the exact same type
public <T extends Set> List<T> somethingElse(List<T> first, List<T> second) {
...
}简单规则:如果在两个地方需要相同的类型,则在方法签名中使用类型变量T extends Foo。方法参数是一个地方,方法返回类型是另一个地方。如果您只需要确保在一个地方处理“某个东西是一个Foo”,请使用通配符? extends Foo。
旁白:不要使用原始类型Set。
发布于 2011-06-08 21:41:25
在声明varlable时使用List<? extends Set>。例如:
List<? extends Number> l = new ArrayList<Integer>();List<T extends Number>可以在类或方法声明中使用。这将允许您稍后在函数中编写T而不是<? extends Number>。
public <T extends Number> int addAll(List<T> list) {
int result = 0;
for (T t : list) {
result += t.intValue();
}
return result;
}https://stackoverflow.com/questions/6279516
复制相似问题