簡體   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