在官方教程#Wildcard Capture和Wildcard Capture and Helper Methods中,其易于理解的演示如下:
public class WildcardFixed {
void foo(List<?> i) {
fooHelper(i);
}
private <T> void fooHelper(List<T> l) {
l.set(0, l.get(0));
}
}
我还阅读了StackOverflow上一些有关通配符捕获的文章,但是当我尝试将其用作
public static <T> void addToSet(Set<T> s, T t) {
// I was hoping the type inference will infer the T to String
}
private static <T> Set<T> setWrapper(Set<T> theSet) {
return theSet;
}
public static void testUnboundedWildcard() {
Set<?> unknownSet = new HashSet<String>();
// ------> here lies the compile error <-------
HelloWorld.<String>addToSet(setWrapper(unknownSet), "abc");
}
显示编译错误
Error:(52, 47) java: incompatible types: inferred type does not conform to equality constraint(s)
inferred: java.lang.String
equality constraints(s): java.lang.String,capture#1 of ?
我以为我可以捕获通配符并将其作为generic method
来处理,但我完全错了。
答案 0 :(得分:2)
为什么我们确实需要它?可以找到任何特定的情况吗?
当您只需要使用基本类型并且真的不在乎泛型时,就可以使用它。
例如,您可以有一个方法
boolean hasTooManyElements(Collection<?> data){
return data.size() > 100;
}
没有通配符,您将不得不(没有充分的理由)将这种方法限制为仅适用于特定类型的Collections。
请注意,通配符仍然可以绑定:
boolean hasEmptyText(Collection<? extends CharSequence> data) {
return data.exists(x -> x.isEmpty());
// you can call `isEmpty` because of the bounded wildcard
}
您也可以通过使方法通用来表达这一点(但是,如果您不打算在任何地方使用类型T
的话,没有什么意义。
<T> boolean hasTooManyElements(Collection<T> data);
在以下情况下,您希望拥有<T>
:
// limit the return type
<T> T getRandomElement(Collection<T> data);
// or, more flexible
<T> T getRandomElement(Collection<? extends T> data);
// make sure the two inputs have the same generic type
<T> boolean areEqual(Collection<T> one, Collection<T> two);