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
是一个通用映射,您不知道元素类型,但它仍然被强制执行,即它不允许您放置任何内容。
您不能向使用通配符参数化的Collection
和Maps
添加值(非null
) ?
。 这是因为通配符不能替代任何对象,它只是一个未知对象。 所以你不能在只接受未知的地图中添加任何(让我们这样说)已知对象。
您只能读取值。