java - 为什么我们需要通配符捕获?

标签 java generics

官方教程中#Wildcard CaptureWildcard 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 的操作但我完全错了。

我的困惑

  1. 为什么我使用通配符捕获的代码无法工作?
  2. 如果它无法正常工作,那么为什么我们到底需要它呢?有什么具体的场景吗?

最佳答案

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/

相关文章:

java - 默认构造函数不初始化类的实例成员?

java - 在 Java 中更改网格大小

java - 为什么这个简单的 Java 通用函数不能编译?

java - 如何在 Java 中创建一个固定大小的泛型数组?

Swift 泛型和扩展需要锻炼

java - 如何通过 Spark 提交 Spark Streaming 应用程序

java - 使用java从另一个字符串中获取特定字符串

java - Java 中的自省(introspection)库

c# - 对于 C#,是否可以在泛型类的实例声明中指定类型约束?

generics - Spring 5 : Programmatically register generic bean