Java Map编译器错误与generics

// 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 is not applicable for the arguments // (String, capture#12-of ?) void trimKeyMap(Map map){ for (String key : map.keySet()) { map.put(StringUtils.trim(key), map.get(key)); // compile error } } 

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

问题是编译器只知道密钥类型是“未知”,但不知道它与Map的密钥类型和get()返回的类型是相同的未知类型(即使我们人类意识到它是相同)。

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

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

Java 5专家组可能可以为generics方法参数类型中的通配符规范添加更多function。 我怀疑由于在规格阶段缺乏时间,增强没有成功。 在这里查看我自己最近的问题: JLS如何指定不能在方法中正式使用通配符?

如果没有更好的解决方案,您必须使您的方法成为通用方法

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

除了null文字之外,您不能在Map类型中放置任何内容:

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

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

如果要保持clean方法签名(trimKeyMap的客户端不必使用generics方法),可以在helper方法中使用类型推断:

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

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

? 不是任何类型的通配符,而是未知类型 。 那么地图只接受? -type对象而不是String 。 这个(相当奇怪的)事实的一个结论是:我们不能将值添加到参数化的集合中?

?Object不同。

Map是一个通用映射,您不知道元素类型,但它仍然被强制执行,即它不允许您放置任何内容。

您不能向使用通配符参数化的CollectionMaps添加值(非null? 。 这是因为通配符不能替代任何对象,它只是一个未知对象。 所以你不能在只接受未知的地图中添加任何(让我们这样说)已知对象。

您只能读取值。