繁体   English   中英

为什么选择HashMap <String, Object> 不接受HashMap <String, List> 实例?

[英]why HashMap<String, Object> not accept HashMap<String, List> instance?

我是Java泛型的新手,面临以下问题。 我有这样的方法,

private static void fillDescriptiveData(HashMap<String, Object> output, String attributeMapping) {
    for (Map.Entry<String, Object> outputInEntry : output.entrySet()) {
        String outputKey = outputInEntry.getKey();
        String outputValue = outputInEntry.getValue().toString();
        outputValue = getDescriptiveDataForOutput(outputKey, outputValue, attributeMapping);
        outputInEntry.setValue(outputValue);
    }
}

现在,如果我按以下方式调用API

HashMap<String, Object> ObjectMap = new HashMap<String, Object>();
HashMap<String, List> listMap = new HashMap<String, List>();
  • fillDescriptiveData(ObjectMap,"here");
    这个工作正常。

  • fillDescriptiveData(listMap,"here"); 这个电话给错误

CustomAttribute类型的方法fillDescriptiveData(HashMap,String)不适用于参数(HashMap,String)`

为什么呢?

为了解决这个问题,我遇到了又一个问题,

private static void fillDescriptiveData(HashMap<String, ? extends Object> output, String attributeMapping) {
    for (Map.Entry<String, ? extends Object> outputInEntry : output.entrySet()) {
        String outputKey = outputInEntry.getKey();
        String outputValue = outputInEntry.getValue().toString();
        outputValue = getDescriptiveDataForOutput(outputKey, outputValue, attributeMapping);
        outputInEntry.setValue(outputValue); /* Error comes at this line */
    }
}

HashMap<String, ? extends Object> ObjectMap = new HashMap<String, Object>();
HashMap<String, List> listMap = new HashMap<String, List>();
fillDescriptiveData(ObjectMap,"here");
fillDescriptiveData(listMap,"here");

行错误outputInEntry.setValue(outputValue);

Map.Entry类型的方法setValue(capture#4-of?extended Object)不适用于参数(String)

为什么呢?

避免此问题的最佳方法是什么?

当您可以使用类型变量时就是这种情况:

private static <T> void  fillDescriptiveData(Map<String, T> output,String attributeMapping)
{
    for(Map.Entry<String, T> outputInEntry : output.entrySet())
    {
        String outputKey = outputInEntry.getKey();
        String outputValue = outputInEntry.getValue().toString();
        outputValue = getDescriptiveDataForOutput(outputKey, outputValue, attributeMapping);
        outputInEntry.setValue((T) outputValue);
    }
}

更具体地说,地图中的第二个类型参数是无界的。 Object在这里不起作用,因为它是特定类。 ? extends Object ? extends Object有点废话。 只有HashMap<String, ?>可以工作,直到您仅阅读地图,但是您将无法在此处放置东西。 所以只有一种方法-使用类型变量。

编辑 :还有一件事:请在可能的地方使用接口。 因此,这里最好使用Map<String, T>而不是HashMap<String, T> Map<String, T> 这不是错误,只是良好而适当的代码风格。

此行的错误:

outputInEntry.setValue(outputValue);

是您总是在输入字符串。 仅当条目类型为? super String此方法才有效? super String ? super String或完全String 因此,它不适用于Map<String, Object>Map<String, List>

似乎您只想将每个值映射到一个字符串。 您可以执行此操作,但是为了确保输入的安全性,您需要创建一个新的Map<String, String> 由于您总是映射到String

例如,如果您传入Map<String, List<?>>和(不安全地)将所有值替换为字符串。 仍然有人可以继续使用传递给函数的Map<String, List<?>> ,但是现在它包含字符串而不是列表作为值。 当他们尝试从中检索List时,会收到类强制转换异常。

像这样:

private static Map<String, String> fillDescriptiveData(HashMap<String, ?> input,
        String attributeMapping) {        
    Map<String, String> output = new HashMap<>();

    for(Entry<String, ?> e : input.entrySet()) {
            String outputKey = e.getKey();
            String outputValue = e.getValue().toString();
            outputValue
                = getDescriptiveDataForOutput(outputKey, outputValue, attributeMapping);
            output.put(outputKey, outputValue);
    }
    return output;
}
Map<String, String> r1 = fillDescriptiveData(ObjectMap, "here");
Map<String, String> r2 = fillDescriptiveData(listMap, "here");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM