【问题标题】:Generic wildcard bounderies in complex types [duplicate]复杂类型中的通用通配符边界
【发布时间】:2016-06-01 20:42:37
【问题描述】:

我不明白generic wildcard bounderies 用法。
您能否解释一下为什么processList 工作得很好,而processMap 在以下示例中因编译错误而失败?我应该如何更改processMap 的签名以使其同时适用于Map<String, List<String>>Map<String, List<Object>>

public void processList(List<? extends Object> list) {
}

public void processMap(Map<String, List<? extends Object>> map) {
}

public void f() {
    List<String> list = new ArrayList<>();
    Map<String, List<String>> map = new HashMap<>();

    processList(list); // OK
    processMap(map); // ERROR
}

虽然将泛型类型定义从方法参数类型移动到方法参数,但成功了

public void processMap(Map<String, List<? extends Object>> map)
public <T extends Object> void processMap(Map<String, List<T>> map)

我现在想知道两者之间的区别。已移至another thread

【问题讨论】:

  • 我不知道我是否正确,但似乎 java 编译器无法解析或转换用作问题中定义的 Map 集合键的集合类型。我这样说是因为当我将函数签名修改为public static &lt;T extends Object&gt; void processMap(Map&lt;? extends Object, List&lt;T&gt;&gt; map) 时,它工作正常。在此类声明中使用时,&lt;T extends Object&gt;&lt;? extends Object&gt; 之间似乎存在很大差异。它的多级通配符概念。

标签: java generics


【解决方案1】:

如果您消除通配符,您可以使其工作。 IE。您创建一个具有命名类型的泛型函数:&lt;T extends Object&gt;

public <T extends Object> void processMap(Map<String, List<T>> map) {
}

public void processList(List<? extends Object> list) {
}

public void f() {
    List<String> list = new ArrayList<>();
    Map<String, List<String>> map = new HashMap<>();

    processList(list); // OK
    processMap(map); // OK now
    processMap(new HashMap<String, List<Integer>>()); // this is OK too
}

很遗憾,我无法解释为什么带有通配符的函数不起作用。

【讨论】:

  • 我认为 why 的原因与wildcard capture 有关。
  • 刚刚发布了相同的内容......唯一的区别:没有必要将extends Object 放在那里。您将使用的任何 T 都将扩展 Object 而无需您告诉编译器 ;-)
  • 是的。现在可以使用&lt;T&gt;extends 适合 &lt;T extends CharSequence&gt; 之类的东西
【解决方案2】:

一半的答案:以下代码确实为我编译。

缺失:一个很好的解释为什么命名的 T 起作用;但是一个未命名的?没有。

public <T> void processMap(Map<String, List<T>> map) {
}

public void f() {
    Map<String, List<String>> map = new HashMap<>();
    processMap(map);
    Map<String, List<Object>> map2 = new HashMap<>();
    processMap(map2);
}

【讨论】:

    【解决方案3】:
    Map<String, List<? extends Object>> map = new HashMap<>();
    

    在 f() 方法中进行上述更改并且它可以工作。 Java编译器检查变量的类型,所以两者应该相同,我可能错了。

    【讨论】:

      猜你喜欢
      • 2012-08-14
      • 2015-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多