如何让 Java 为我的类型安全映射文字推断正确的通用映射类型?
我正在尝试在 java 中编写一个类型安全的映射文字帮助程序类,它可以生成任何类型的映射,并让编译器检查所有给定的键和值是否符合映射的类型。对于具有两个值的映射,将有一个具有以下签名的函数:
public static <KEY, VALUE> Map<KEY, VALUE> make(final KEY key1,
final VALUE value1,
final KEY key2,
final VALUE value2)
现在我预计类似的事情是可能的:
Map<Integer, Object> map = make(1, "bla", 3, 17);
但是我收到编译器错误:
Type mismatch: cannot convert from Map<Integer,Object&Serializable&Comparable<?>> to
Map<Integer,Object>
有没有办法解决这个问题?当然,用签名 make(Object...keysAndValues)
定义一个函数是可行的,但我会失去编译时类型安全性。 :-(
I am trying to write a typesafe map literal helper class in java that can generate maps of any type and have the compiler check that all given keys and values conform to the type of the map. For a map with two values there would be a function with the following signature:
public static <KEY, VALUE> Map<KEY, VALUE> make(final KEY key1,
final VALUE value1,
final KEY key2,
final VALUE value2)
Now I would have expected that something like this would be possible:
Map<Integer, Object> map = make(1, "bla", 3, 17);
However I get an compiler error:
Type mismatch: cannot convert from Map<Integer,Object&Serializable&Comparable<?>> to
Map<Integer,Object>
Is there a way to fix this? Of course, defining a function with signature make(Object... keysAndValues)
would work, but I would loose the compile time typesafety. :-(
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
错误可能在这里:
VALUE >无法从
String
和Integer
推断对象请尝试以下任一操作:
The error is probably here:
VALUE > Object
can't be inferred from bothString
andInteger
Try any of these:
如果您在调用方法中修改地图的签名,您的代码将起作用:
make
无需进行任何更改Make
的调用方您必须将
Map
更改为Map
:编辑1:OpenJDK 1.6 + Eclipse Indigo编译器
编辑2:在构建这样的通用映射时,您必须接受在检索值时必须进行向下转换。
EDIT3:有办法解决这个问题吗?当然,用签名 make(Object...keysAndValues) 定义一个函数是可行的,但我会失去编译时类型安全性。
在某个时刻,你总是会失去编译时安全性。至少在检索方面是这样。
Your code will work if you modify the Map's signature in the calling method:
No changes required to
make
Make
's callerYou must change
Map<String, Object>
toMap<String, ? extends Object>
:EDIT1: OpenJDK 1.6 + Eclipse Indigo compiler
EDIT2: When building generic maps like that, you must accept that you have to downcast when it comes to retrieving the values.
EDIT3: Is there a way to fix this? Of course, defining a function with signature make(Object... keysAndValues) would work, but I would loose the compile time typesafety.
You will always loose compile time safety at a certain point. At least when it comes to retrieval.
这确实可以编译:
这就是 Java 的泛型类型推断为您提供的功能。不是你所期望的吗?
您有几个选择,要么在方法上使用澄清符:
或者您可以使用没有公共父接口的对象。
This does compile:
This is what Java's generic type inference is giving you. Not what you expected?
You have a couple of options, either use a clarifier on the method:
Or you can use objects that don't have a common parent interface.
编译器必须根据给定的参数“猜测”类型
KEY
和VALUE
(存储返回值的Map
类型为忽略)。VALUE
的“猜测”是最严格的适合 Integer 和 String 的类型:任何实现 Comparable 和 Serialized (Object&Serialized&Comparable
) 的类型。您有两种选择:将至少一个 VALUE 转换为对象:
或在映射中使用通配符
The compiler has to "guess" the types
KEY
andVALUE
from the parameters given (the types of yourMap
where you store the return value are ignored). The "guess" forVALUE
is the strictest type fitting to both Integer and String: anything that implements Comparable and Serializable (Object&Serializable&Comparable<?>
).You have two options: casting at least one VALUE to Object:
or using a wildcard in your map
String
实际上实现了Serializable
和Comparable
接口,而 Object 没有..所以它说的 Object 没有实现,但它的隐式 typeCasted String 却实现了...String
actually implements bothSerializable
andComparable
interface and Object does't.. so its saying Object does't implement but Its implicict typeCasted String does...下面的解决方案看起来应该可以工作,但奇怪的是它只能在 Eclipse 编译器中工作,而不能在普通的 Java 6 编译器上工作。 8-{为什么???
方法声明非常复杂,但在创建映射时允许使用最简单的语法:
这里,编译器从上下文中推断
KEY 应该是 Integer,VALUE 应该是 Object; AKEY 是从给定参数推断为 Integer 和 AVALUE 为 Object&Serialized&Comparable ,编译器可以验证 AKEY 符合 KEY 且 AVALUE 符合 VALUE 。
The following solution looks like it should work, but strangely it does only work in the Eclipse compiler, but not on a plain Java 6 compiler. 8-{ Why???
The method declaration is annoyingly complicated but allows the simplest syntax when creating maps:
Here, the compiler infers from the context in
that KEY should be Integer and VALUE should be Object; AKEY is inferred from the given parameters as Integer and AVALUE as Object&Serializable&Comparable , and the compiler can verify that AKEY conforms to KEY and AVALUE to VALUE.