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