使用类<?>创建ImmutableMap问题作为关键 [英] Issue creating ImmutableMap with Class<?> as key

查看:1517
本文介绍了使用类<?>创建ImmutableMap问题作为关键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个 ImmutableMap 将类映射到字符串(注意:这当然是一个例子!但是,像

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

给我以下错误

 类型不匹配:无法从ImmutableMap转换< Class< ;? extends Object& Comparable<?& Serializable>,String>到ImmutableMap< Class<?>,String> 

奇怪的是,如果我添加一个cast到 Class<?> ; 到任何(!)键,即

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

会正常工作。我对这种行为感到困惑:对于一个,为什么它不工作没有casts?所有这些都是类,它真的没有得到比类<?> 更通用,所以为什么它不工作?其次,为什么在任何一个键上的演员都可以工作?



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



编辑:我实际上只是想出这将工作,但我会stil喜欢了解上述行为

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


解决方案

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



Class< Date> Class< Integer> 可捕获到以下所有内容:




  • 类< ;? extends Object>

  • Class< ;? extends Serializable>

  • 类< ;? extends Comparable<>>



/ code>被推断为所有的混合:

  K:= Class< ;? extends Object& Serializable& Comparable<?>> 

这是方法的返回值真正是:

  ImmutableMap< Class< ;? extends Object& Serializable& Comparable<?>>,String> 

当然,你不能直接赋值给 ImmutableMap< Class< ?>,String> ,因为它们是不兼容的类型。还要注意,您不能如上所述明确地声明您的地图,因为您不能给通配符多个边界。



对于这种情况,编译器无法根据需要正确推断类型参数,可以传递 >显式类型参数 ,而方法调用是您在上次尝试时执行的操作:

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

这将工作,因为编译器从显式类型参数知道返回值将是类型 - ImmutableMap< Class<?>,String>


如果我向类中添加任何(!)键



$

b $ b

一旦您将类 类的任何一个类型转换为,则 Class<?& code>表示家庭类< T> 的所有所有实例,因此它是所有 Class 实例。因此,类型参数将自动推断为 Class<?> 。它会工作得很好。


I am trying to create an ImmutableMap that maps classes to strings (note: this is, of course, just an example!). However, something like

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

gives me the following error

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

Oddly enough it does work if I add a cast to Class<?> to any(!) of the keys, i.e.

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

will work just fine. I'm sort of puzzled by this behavior: For one, why does it not work without casts? All of these are classes and it really doesn't get any more generic than Class<?>, so why does it not work? Secondly, why does a cast on any one of the keys get it to work?

(side note: if you're wondering why I even want to do such a thing – yes, it's because of Reflection…)

Edit: I actually just figured out that this will work, but I'd stil like to understand the above behavior

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

解决方案

This is how the compiler infers type parameters when you pass inconsistent method arguments. If you notice, the ImmutableMap.of(K, V, K, V) method uses the same type parameter K for both Date and Integer. One would think that this should fail as we are passing inconsistent method arguments, means we are passing different types for the same type parameter K. But surprisingly it doesn't.

Class<Date> and Class<Integer> are capture convertible to all of the following:

  • Class<? extends Object>
  • Class<? extends Serializable>
  • Class<? extends Comparable<?>>

So, the type K is inferred as a mixture of all:

K := Class<? extends Object&Serializable&Comparable<?>>

That is the return value of the method would really be:

ImmutableMap<Class<? extends Object&Serializable&Comparable<?>>, String>

Of course, you can't assign it directly to ImmutableMap<Class<?>, String>, as they are incompatible type. Also note that, you can't declare your map explicitly as above, because you can't give multiple bounds for wildcards. It's just how the compiler infers the type.

For these kinds of situation, where compiler cannot correctly infer the type arguments as you required, you can pass explicit type arguments, while method invocation, which is what you did in your last try:

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

This will now work, as compiler knows from the explicit type argument that the return value would be of type - ImmutableMap<Class<?>, String>

Oddly enough it does work if I add a cast to Class<?> to any(!) of the keys

As soon as you type cast any of the element to Class<?>, since Class<?> denotes family all all the instances of Class<T>, and hence it is the common supertype for all the Class instances. So, the type argument will be inferred as Class<?> automatically. And it would work fine.

这篇关于使用类&lt;?&gt;创建ImmutableMap问题作为关键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆