问题
Say I have a
HashMap<?, List<?>> map = new HashMap<>();
map.put(String.class, new ArrayList<Long>());
The following code will compile.
However, I want to fail compilation because the ArrayList is not for String type.
Also, my wildcard is limited to some specific interface (e.g. Exception), so I suppose I should put that <? extends Exception>
somewhere.
How can I achieve the above?
Example Test:
map.put(String.class, new ArrayList<String>()); //Fail because String is not an Exception
map.put(IOException.class, new ArrayList<FileNotFoundException>()); // Fail because FileNotFoundException is not an IOException even though it is a subclass of it
map.put(FileNotFoundException.class, new ArrayList<IOException>()); // I suppose I'm fine with this.
map.put(IllegalArgumentException.class, new ArrayList<IllegalArgumentException>()); // Succeed
map.put(NumberFormatException.class, new ArrayList<ServerException>()); // Fail again because the two classes don't match
map.put(ClientDecodingException.class, new ArrayList<ClientDecodingException.class>); // Succeed again since the map takes in a wildcard Exception
回答1:
I beleive you can't express such a generic constraint between your map's key and value on declaration. You could declare the map as a
Map<Class<Exception>, List<Exception>>
but then the compiler won't know that the exceptions in the list must extend the key's class.
I don't see a lot of ways of ensuring this constraint is checked except by using a method such as
<T extends Exception> void addToMap(Class<? extends T> aClass, List<T> aList) {
map.put(aClass, aList);
}
Hope this helps.
回答2:
I've done this by using raw Class
and List
(still cannot fix this) and by using a map wrapper for storing Exception
only:
public class ExceptionMapWrapper {
private Map<Class, List> myMap;
public ExceptionMapWrapper() {
myMap = new HashMap<>();
}
//relevant methods for the test: put and get
public <T extends Exception> void put(Class<T> clazz, List<T> list) {
myMap.put(clazz, list);
}
public <T extends Exception> List<T> get(Class<T> key) {
return myMap.get(key);
}
}
And a simple test for this:
ExceptionMapWrapper exceptionMapWrapper = new ExceptionMapWrapper();
Class<IOException> clazz = IOException.class;
List<IOException> list = new ArrayList<>();
exceptionMapWrapper.put(clazz, list);
//compiler errors, uncomment to see them
//exceptionMapWrapper.put(String.class, new ArrayList<String>());
//exceptionMapWrapper.put(IOException.class, new ArrayList<ClassCastException>());
//exceptionMapWrapper.put(IOException.class, new ArrayList<SQLException>());
List<IOException> ioExList = exceptionMapWrapper.get(clazz);
//compiler error, uncomment to see
//List<SQLException> sqlExList = exceptionMapWrapper.get(clazz);
来源:https://stackoverflow.com/questions/30383942/how-to-say-a-map-of-class-to-listthe-class-in-java