Java映射编译器错误,带有泛型 //我知道这个方法会生成重复的 //修剪相同值的关键点,但我只是 //试图理解为什么会出现编译错误: //方法将(字符串、捕获#11 of?)放入类型中 //映射不适用于参数 //(字符串,捕获#12个?) 无效trimKeyMap(贴图贴图贴图){ for(字符串键:map.keySet()){ map.put(StringUtils.trim(key),map.get(key));//编译错误 } }

Java映射编译器错误,带有泛型 //我知道这个方法会生成重复的 //修剪相同值的关键点,但我只是 //试图理解为什么会出现编译错误: //方法将(字符串、捕获#11 of?)放入类型中 //映射不适用于参数 //(字符串,捕获#12个?) 无效trimKeyMap(贴图贴图贴图){ for(字符串键:map.keySet()){ map.put(StringUtils.trim(key),map.get(key));//编译错误 } },java,generics,map,Java,Generics,Map,为什么我们要输入的值map.get(key)可以来自不同的类型??不是任何类型的通配符,而是未知类型。因此,映射只接受?类型的对象,而不接受字符串。从这个(相当奇怪的)事实得出的一个结论是:我们不能向使用?参数化的集合添加值,Java 5专家组可能会在泛型方法参数类型中为通配符的规范添加多一点功能。我怀疑这项改进没有成功,因为在规格阶段没有足够的时间。请看我最近的问题: 如果没有更好的解决方案,您必须使您的方法成为通用方法: void <V> trimKeyMap(Map<St

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

不是任何类型的通配符,而是未知类型。因此,映射只接受
类型的对象,而不接受
字符串。从这个(相当奇怪的)事实得出的一个结论是:我们不能向使用

参数化的集合添加值,Java 5专家组可能会在泛型方法参数类型中为通配符的规范添加多一点功能。我怀疑这项改进没有成功,因为在规格阶段没有足够的时间。请看我最近的问题:

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

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

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

对象不同

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

您不能将值(非
null
)添加到
集合
映射
使用通配符
参数化。这是因为通配符不能替代任何对象,它只是一个未知对象。因此,您不能在只接受未知对象的贴图中添加任何(让我们这样说)已知对象


您只能读取值。

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

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

Map<String, ?> map = new HashMap<String, String>();
map.put("A", null); // Works
map.put("B", "X"); // Doesn't work.
void trimKeyMap(地图地图){
for(字符串键:map.keySet()){
map.put(StringUtils.trim(键),map.get(键));
}
}

如果希望保留干净的方法签名,可以在助手方法中使用类型推断(trimKeyMap的客户端不必使用泛型方法):

void trimKeyMap(最终贴图){
for(最后一个字符串键:map.keySet()){
修剪(地图、钥匙);
}
}
专用空心修剪(最终贴图、最终字符串键){
map.put(StringUtils.trim(键),map.get(键));
}

这被称为通配符捕获,并在此处进行了详细讨论:

请注意,输入一个完全不受限制的
V
就足够了。这只是为了弄清楚两个“未知”是“相同的未知”。显然你可以添加
null
,但除此之外,这个答案似乎是正确的。试图证明你错了,但失败了,所以现在我同意你的看法。当然,但我指的是非null对象。我必须更加明确。我记得,我曾多次使用声明,但同时我也了解到,我一直在阅读这些变量……但很遗憾,javac无法生成一些变量来处理这种直观的“通配符捕获”情况
Map<String, ?> map = new HashMap<String, String>();
map.put("A", null); // Works
map.put("B", "X"); // Doesn't work.
void <V> trimKeyMap(Map<String, V> map) {
    for (String key : map.keySet()) {
        map.put(StringUtils.trim(key), map.get(key));
    }
}
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));
}