以Class 为关键创建ImmutableMap的问题

我正在尝试创建一个将类映射到字符串的ImmutableMap (注意:这当然只是一个例子!)。 但是,像

 ImmutableMap<Class, String> map = ImmutableMap.of( Integer.class, "Integer", Date.class, "Date" ); 

给我以下错误

 Type mismatch: cannot convert from ImmutableMap<Class<? extends Object&Comparable&Serializable>,String> to ImmutableMap<Class,String> 

奇怪的是,如果我将一个强制转换为Class到任何(!)的键,即

 ImmutableMap<Class, String> map = ImmutableMap.of( Integer.class, "Integer", Date.class, "Date", (Class) String.class, "String", long.class, "Long" ); 

会工作得很好。 我有点对这种行为感到困惑:首先,为什么没有演员表它不起作用? 所有这些都是类,它实际上没有比Class更通用,所以为什么它不起作用? 其次,为什么任何一个键上的强制转换都能使它工作?

(旁注:如果你想知道为什么我甚至想做这样的事情 – 是的,这是因为反思…)

编辑:我实际上只是发现这会起作用,但我仍然想了解上述行为

 ImmutableMap<Class, String> map = ImmutableMap.<Class, String>builder() .put( Integer.class, "Integer" ) .put( Date.class, "Date" ) .build(); 

这是编译器在传递不一致的方法参数时推断类型参数的方式。 如果您注意到, ImmutableMap.of(K, V, K, V)方法对DateInteger使用相同的类型参数K 人们会认为这会失败,因为我们传递的是不一致的方法参数,意味着我们为相同的类型参数K传递不同的类型。 但令人惊讶的是它没有。

ClassClass是可以转换为以下所有内容的:

  • Class
  • Class
  • Class>

因此,类型K被推断为所有的混合:

 K := Class> 

那个方法的返回值实际上是:

 ImmutableMap>, String> 

当然,您不能将它直接分配给ImmutableMap, String> ,因为它们是不兼容的类型。 另请注意,您无法像上面那样明确声明地图,因为您无法为通配符提供多个边界。 这就是编译器推断类型的方式。

对于这些情况,编译器无法正确地根据需要推断类型参数,您可以在方法调用时传递显式类型参数 ,这是您在上次尝试时所做的:

 ImmutableMap, String> map = ImmutableMap., String>of( Integer.class, "Integer", Date.class, "Date" ); 

现在这将起作用,因为编译器从显式类型参数知道返回值的类型是什么 – ImmutableMap, String>

奇怪的是,如果我向Class添加一个强制转换为任何(!)的键,它确实有效

只要键入任何元素到Class ,就会将Class表示为Class所有实例,因此它是所有Class实例的公共超类型。 因此,type参数将自动推断为Class 。 它会工作正常。