以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)
方法对Date
和Integer
使用相同的类型参数K
人们会认为这会失败,因为我们传递的是不一致的方法参数,意味着我们为相同的类型参数K
传递不同的类型。 但令人惊讶的是它没有。
Class
和Class
是可以转换为以下所有内容的:
-
Class extends Object>
-
Class extends Serializable>
-
Class extends Comparable>>
因此,类型K
被推断为所有的混合:
K := Class extends Object&Serializable&Comparable>>
那个方法的返回值实际上是:
ImmutableMap>, String>
当然,您不能将它直接分配给ImmutableMap
,因为它们是不兼容的类型。 另请注意,您无法像上面那样明确声明地图,因为您无法为通配符提供多个边界。 这就是编译器推断类型的方式。
对于这些情况,编译器无法正确地根据需要推断类型参数,您可以在方法调用时传递显式类型参数 ,这是您在上次尝试时所做的:
ImmutableMap, String> map = ImmutableMap., String>of( Integer.class, "Integer", Date.class, "Date" );
现在这将起作用,因为编译器从显式类型参数知道返回值的类型是什么 – ImmutableMap
奇怪的是,如果我向
Class>
添加一个强制转换为任何(!)的键,它确实有效
只要键入任何元素到Class>
,就会将Class>
表示为Class
所有实例,因此它是所有Class
实例的公共超类型。 因此,type参数将自动推断为Class>
。 它会工作正常。