泛型和变量赋值问题

时间:2015-12-18 12:43:39

标签: java generics

我有两张地图Something1Something2。两者都扩展了类Something

Map<Class<? extends Something1>, String> m1
Map<Class<? extends Something2> ,String> m2

我想创建一个更通用的地图m3,我可以像这样分配m1m2

Map<Class<? extends Something>, String> m3 = m1;

但是我得到以下例外:

Type mismatch: cannot convert from Map<Class<? extends Something1>, String> to Map<Class<? extends Something>, String>

我也尝试使用Class<?>,但它似乎无法正常工作。

我做错了什么?

2 个答案:

答案 0 :(得分:2)

这是不可能的。请考虑以下事项:

Map<Class<? extends Something1>, String> m1 = new HashMap<>();
m1.put(Something1.class, "Something1"); // OK
m1.put(Something2.class, "Something2"); // Error

因此,您无法将Something2作为密钥。

相反:

Map<Class<? extends Something2>, String> m2 = new HashMap<>();
m2.put(Something1.class, "Something1"); // Error
m2.put(Something2.class, "Something2"); // OK

在此,您无法将Something1作为密钥。

但是,如果您创建一个使用基类作为通配符的版本,它就可以工作。看看这个:

Map<Class<? extends Something>, String> m = new HashMap<>();
m.put(Something1.class, "Something1"); // OK
m.put(Something2.class, "Something2"); // OK

您的问题是您正在尝试为通用类型分配更具体的类型。像这样:

m = m1; // Boom, but why?

为什么这不起作用。好吧,这是因为如果你允许这个任务,你就可以这样做:

m.put(Something2.class, "Something2"); 

从那以后你会把Something2作为Something1类型地图的关键字,显然不行。

答案 1 :(得分:0)

非通配符类型参数必须完全相同才能兼容。 Class<? extends Something1>Class<? extends Something>不完全相同(即使其中一个是另一个的子类型),因此Map的{​​{1}}与Map的{​​{1}}不兼容另一个。

如果你想要一个可以接受具有不同类型参数的Map的类型,你需要在顶层有一个通配符(但请注意,这将有效地使Map只读):< / p>

Map<? extends Class<? extends Something>, String> m3 = m1;