3
// 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)可以来自不同的类型?

4

6 回答 6

10

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

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

void <V> trimKeyMap(Map<String, V> map) {
    for (String key : map.keySet()) {
        map.put(StringUtils.trim(key), map.get(key));
    }
}
于 2013-06-20T12:13:47.830 回答
3

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

缺少更好的解决方案,您必须使您的方法成为通用方法

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

Map<String, ?>除了null文字之外,您不能在类型中添加任何内容:

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

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

于 2013-06-20T12:12:11.560 回答
2

如果你想保持干净的方法签名,你可以在辅助方法中使用类型推断(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/

于 2013-06-20T12:20:02.353 回答
1

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

于 2013-06-20T12:11:53.257 回答
1

?不同于Object.

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

于 2013-06-20T12:12:32.317 回答
0

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

您只能读取值。

于 2013-06-20T12:12:52.673 回答