How to say “A Map of Class<?> to List<The class>” in Java?

左心房为你撑大大i 提交于 2019-12-11 03:47:59

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!