我正在尝试创建一个将类映射到字符串的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,"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.但令人惊讶的是它没有.
类<日期和GT;和Class< Integer>被捕获可以转换为以下所有内容:
> Class<?扩展对象>
> Class<?扩展Serializable>
> Class<?扩展可比较的<?>>
所以,K类推断为所有的混合物:
K := Class<? extends Object&Serializable&Comparable<?>>
那就是方法的返回值真的是:
ImmutableMap<Class<? extends Object&Serializable&Comparable<?>>,String>
当然,您不能将它直接分配给ImmutableMap< Class<?> String>,因为它们是不兼容的类型.另请注意,您不能像上面那样明确地声明您的地图,因为您无法给出通配符的多个边界.这只是编译器推断的类型.
对于这些情况,编译器无法根据需要正确推断类型参数,您可以传递显式类型参数,而方法调用,这是您最后一次尝试中所做的:
ImmutableMap<Class<?>,String>of( Integer.class,"Date" );
现在这将工作,因为编译器从显式类型参数中知道返回值将为 – ImmutableMap< Class<?>,String>
Oddly enough it does work if I add a cast to
Class<?>
to any(!) of the keys
一旦您将任何元素转换为Class<?>,因为Class<?>表示家庭所有所有类< T>的所有实例,因此它是所有Class实例的公共超类型.因此,type参数将被推断为Class<?>自动.它会工作正常.