如何获取具有多个泛型类型的类型以匹配类型参数?

时间:2016-04-26 12:54:33

标签: java generics

例如,假设我想要Map<Class<?>, List<?>>,所以我可以放入一个类并输出该类型的列表 - 是否有什么东西可以替换问号来实现这一点?

3 个答案:

答案 0 :(得分:4)

如果将类型检查委托给方法,则可以执行此操作:

private class TypedMap {
    private Map<Class<?>, List<?>> map = new HashMap<>();

    public <T> void put(Class<T> key, List<T> value) {
        map.put(key, value);
    }

    @SupressWarnings("unchecked")
    public <T> List<T> get(Class<T> clazz) {
        return (List<T>) map.get(clazz);
    }
}
  • 地图声明中的通配符?无法确保键Class<?>和值List<?>的类型相同。方法put()确保了这一点。如果您的课程不是通用的,那么您无法将地图声明为Map<Class<T>, List<T>> - 这就是您必须使用某种方法的原因。

  • 取消选中获取方法。如果使用put()方法添加条目,则强制转换是安全的。 (原始类型仍存在问题 - 但这是不可避免的)

  • 您可以向TypedMap类添加更多方法,但请记住这些限制。

public static void main(String[] args) {
    TypedMap map = new TypedMap();
    List<Cat> cats = new ArrayList<>();
    List<Dog> dogs = new ArrayList<>();
    adder.put(Cat.class, cats);
    adder.put(Dog.class, dogs);

    adder.put(Cat.class, dogs); // compilation error
}

答案 1 :(得分:2)

Java没有完全强制执行此操作,但至少要对其发出警告的一种方法是使用封装:

public class MyClass {
    // private, private, private
    private Map<Class<?>, List<?>> myMap;

    public <T> void put(Class<T> clazz, List<T> list) { // both must have the same T.
        myMap.put(clazz, list);
    }
    ...
}

您仍然可以通过执行以下操作来解决此问题:

MyClass mc = new MyClass();
Class c = Main.class;       
List<String> l = new ArrayList<String>();       
mc.put(c, l);

但是,您至少会收到关于未经检查的c转换为Class<String>的警告。未经检查的MyClass::put

调用

答案 2 :(得分:0)

不确定您在此处尝试完成的任务,但Map<Class<T>, List<T>>将是最接近的事情。 T是一种单一类型,因此您无法将多个类放入一个Map

如果您尝试将不同类的对象放入同一ClassCastException中,您将获得Map