官方教程中#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
的操作但我完全错了。
我的困惑
- 为什么我使用通配符捕获的代码无法工作?
- 如果它无法正常工作,那么为什么我们到底需要它呢?有什么具体的场景吗?
最佳答案
why exactly we need it? any specific scenarios can be found?
当您只需要使用基本类型并且真正不关心泛型类型时,可以使用它。
例如,您可以有一个方法
boolean hasTooManyElements(Collection<?> data){
return data.size() > 100;
}
如果没有通配符,您将不得不(没有充分的理由)限制此方法仅适用于特定类型的集合。
请注意,通配符仍然可以有界:
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);
关于java - 为什么我们需要通配符捕获?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55086197/