【问题标题】:Java Map compiler error with generic泛型的 Java Map 编译器错误
【发布时间】:2013-06-20 12:08:32
【问题描述】:
// I know that this method will generated duplicate 
// trim keys for the same value but I am just
// trying to understand why we have a compile error:
// The method put(String, capture#11-of ?) in the type
// Map<String,capture#11-of ?> is not applicable for the arguments
// (String, capture#12-of ?)

void trimKeyMap(Map<String, ?> map){
  for (String key : map.keySet()) {
    map.put(StringUtils.trim(key), map.get(key)); // compile error
  }
}

为什么我们要放入map.get(key) 的值可能来自不同的类型?

【问题讨论】:

    标签: java generics map


    【解决方案1】:

    问题是编译器只知道键类型是“未知”,但不知道 Map 的键类型和 @987654321 返回的类型是 相同 未知类型@(尽管我们人类意识到它是一样的)。

    如果你想让它工作,你必须通过键入你的方法告诉编译器它是相同未知类型,例如:

    void <V> trimKeyMap(Map<String, V> map) {
        for (String key : map.keySet()) {
            map.put(StringUtils.trim(key), map.get(key));
        }
    }
    

    【讨论】:

    • 请注意,输入完全不受限制的V 就足够了。这只是为了处理两个“未知数”是“相同的未知数”。
    【解决方案2】:

    Java 5 专家组可能会为泛型方法参数类型中的通配符规范添加更多功能。我怀疑由于规范阶段没有时间,增强功能没有成功。在这里查看我自己最近的问题:How does the JLS specify that wildcards cannot be formally used within methods?

    没有更好的解决方案,你必须让你的方法成为一个通用方法

    <V> void trimKeyMap(Map<String, V> map){
      for (String key : map.keySet()) {
        map.put(StringUtils.trim(key), map.get(key));
      }
    }
    

    你不能在 Map&lt;String, ?&gt; 类型中放入任何东西,除了 null 字面量:

    Map<String, ?> map = new HashMap<String, String>();
    map.put("A", null); // Works
    map.put("B", "X"); // Doesn't work.
    

    编译器不知道映射的值参数类型是String。因此,即使您从地图本身获取值,它也不能允许您向地图添加任何内容。

    【讨论】:

      【解决方案3】:

      如果你想保持干净的方法签名,你可以在辅助方法中使用类型推断(trimKeyMap 的客户端不应该使用泛型方法):

      void trimKeyMap(final Map<String, ?> map) {
          for (final String key : map.keySet()) {
              trim(map, key);
          }
      }
      
      private <T> void trim(final Map<String, T> map, final String key) {
          map.put(StringUtils.trim(key), map.get(key));
      }
      

      这称为通配符捕获,在此处进行更多讨论:http://www.ibm.com/developerworks/library/j-jtp04298/

      【讨论】:

      【解决方案4】:

      ? 不是 any 类型的通配符,而是 未知类型。所以地图只接受?-type 对象而不接受String。从这个(相当奇怪的)事实得出的一个结论是:我们不能向使用 ? 参数化的集合添加值。

      【讨论】:

        【解决方案5】:

        ?Object 不同。

        Map&lt;String, ?&gt; 是一个通用映射,您不知道元素类型,但它仍在强制执行,即它不允许您放置任何内容。

        【讨论】:

          【解决方案6】:

          您不能将值(不是null)添加到使用通配符 ? 参数化的Collections 和Maps。这是因为 wildcard 不能替代任何对象,它只是一个 unknown 对象。所以你不能在只接受 unknown 的地图中添加任何(让我们这么说)已知对象。

          您只能读取值。

          【讨论】:

          • 显然你可以添加null,但除此之外,这个答案似乎是正确的。
          • 试图证明你错了,但失败了,所以现在我同意你的看法。
          • 当然,但我指的是非空对象。我必须更明确。
          • 我记得,我曾多次使用 , ?> 声明,但正如我在此期间了解到的,我一直在阅读这些变量...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-16
          • 2010-11-19
          • 2012-04-21
          • 2016-10-30
          • 1970-01-01
          • 2012-10-17
          相关资源
          最近更新 更多