I am new in java generics and facing following issues. I have have method like,
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);
}
}
Now if I call API as below way
HashMap<String, Object> ObjectMap = new HashMap<String, Object>();
HashMap<String, List> listMap = new HashMap<String, List>();
fillDescriptiveData(ObjectMap,"here");
this one working fine.
fillDescriptiveData(listMap,"here");
this call gives error
The method fillDescriptiveData(HashMap, String) in the type CustomAttribute is not applicable for the arguments (HashMap, String)`
why ?
In row to solve this issue I encounter with one more issue,
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");
error at line - outputInEntry.setValue(outputValue);
The method setValue(capture#4-of ? extends Object) in the type Map.Entry is not applicable for the arguments (String)
why ?
What is the best way to avoid this issues ?
This is the case when you could use type variables:
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);
}
}
More specifically, your second type-parameter in the map is unbounded. Object
will not work here as it is specific class. ? extends Object
? extends Object
is somewhat nonsense. Just HashMap<String, ?>
would work until you will just read the map, but you will not be able to put something here. So only one way - using type variable.
EDIT : One more thing: please, use interfaces where it's possible. So here instead of HashMap<String, T>
better use Map<String, T>
. It isn't a mistake, just good and proper style of code.
The error with this line:
outputInEntry.setValue(outputValue);
Is that you're always putting a string into the entry. This will only work if the entry is of type ? super String
? super String
, or exactly String
. So it will not work for a Map<String, Object>
or Map<String, List>
.
It seems like you just want to map each value to a string. You can do it, but to be type safe, you need to create a new Map<String, String>
. Since you're always mapping to a String
.
If you for instance pass in a Map<String, List<?>>
and (unsafely) replace all the values with strings. Someone could still keep using the Map<String, List<?>>
that was passed into the function, but it now contains strings as values instead of lists. When they try to retrieve a List
from it they get a class cast exception.
Something like this:
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");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.