java 具有相关类型的通用键/值的通用映射
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2208317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generic Map of Generic key/values with related types
提问by RHSeeger
I'm trying to create a generic type that keeps a map of the versions of itself that have been created for later use. Effectively, it's an singleton pattern where there's one instance per type. The code I have so far is:
我正在尝试创建一个通用类型,该类型保留已创建供以后使用的自身版本的映射。实际上,这是一种单例模式,其中每种类型有一个实例。我到目前为止的代码是:
public class FieldBinder<T> {
static final Map<Class<? extends Object>,FieldBinder<? extends Object>> instanceMap =
new HashMap<Class<? extends Object>,FieldBinder<? extends Object>>();
private FieldBinder() {}
synchronized public static <V extends Object> FieldBinder<V> getInstance(Class<V> klass) {
if(!instanceMap.containsKey(klass)) {
instanceMap.put(klass, new FieldBinder<V>());
}
return (FieldBinder<V>)instanceMap.get(klass);
}
}
However, I'm still unsure that I'm "doing it right". It feels like I should be able to specify that the collection is (Class -> FieldBinder). The fact that the IDE is warning about the return statement only reinforces this thought.
但是,我仍然不确定我是否“做得对”。感觉我应该能够指定集合是 (Class -> FieldBinder)。IDE 对 return 语句发出警告这一事实只会强化这种想法。
Is there a better way to handle this?
有没有更好的方法来处理这个问题?
Note: This questionseems very closely related, but just far enough away that I can't figure out how to apply the information in it to my own problem.
注意:这个问题似乎非常相关,但距离太远以至于我无法弄清楚如何将其中的信息应用于我自己的问题。
采纳答案by Itay Maman
Your implementation is correct. There's no "better" way of doing it (if there is such a thing is "better" in code, which is another issue..)
您的实施是正确的。没有“更好”的方法来做到这一点(如果有这样的东西在代码中“更好”,这是另一个问题..)
Minor fixes:
小修正:
<V extends Object>is equivalent toVwhich is less verboseClass<? extends Object>is equivalent toClass<?>which is less verbose- You can use the
@SuppressWarnings("unchecked")annotation to tell your compiler that the cast is safe
<V extends Object>相当于V哪个不那么冗长Class<? extends Object>相当于Class<?>哪个不那么冗长- 您可以使用
@SuppressWarnings("unchecked")注释告诉编译器该转换是安全的
回答by finnw
I don't think it can be done without having an unchecked cast somewhere. You would need something similar to Haskell's existential types, which Java does not have.
我认为如果没有在某处进行未经检查的演员表就无法完成。您将需要类似于 Haskell 的existential types 的东西,而Java 没有。
You could make the clientperform the unchecked cast instead...
您可以让客户端执行未经检查的强制转换...
synchronized public static <V> FieldBinder<V>
getInstance(Class<V> klass, Class<FieldBinder<V>> binderKlass) {
if(!instanceMap.containsKey(klass)) {
instanceMap.put(klass, new FieldBinder<V>());
}
return binderKlass.cast(instanceMap.get(klass));
}
Now if the client passes a Class<FieldBinder<V>>to the getInstance()method you can avoid the unchecked cast within getInstance().
现在,如果客户端将 a 传递Class<FieldBinder<V>>给该getInstance()方法,您可以避免在getInstance().
Unfortunately creating a Class<FieldBinder<V>>itself requires an unchecked cast.
不幸的是,创建 aClass<FieldBinder<V>>本身需要未经检查的演员表。
Class<FieldBinder<Integer>> binderKlass =
(Class<FieldBinder<Integer>>) (Class<?>) FieldBinder.class;
BinderAssociator.getInstance(Integer.class, binderKlass);
回答by dma_k
RHSeeger, I got your original question. I found no solution for the problem. What you can try to play with is a MyMap class, which makes the binding as you request. However with this map two problems arise:
RHSeeger,我得到了你最初的问题。我没有找到解决问题的方法。您可以尝试使用的是 MyMap 类,它根据您的要求进行绑定。然而,这张地图出现了两个问题:
- As it is declared as
MyMap<?>, one cannot add something with a given type to it. That's dummy and I refer you to Java Generics FAQs(see case study 3) for more details. - As map has connection between key and value, one cannot add two independent objects of any type (two
<?>refer to different types) because these two types may be not connected.
- 由于它被声明为
MyMap<?>,因此不能向其添加具有给定类型的内容。这是假的,我建议您参阅Java 泛型常见问题解答(请参阅案例研究 3)以了解更多详细信息。 - 由于map有key和value的联系,所以不能添加两个独立的任何类型的对象(两个
<?>是指不同的类型),因为这两个类型可能没有联系。
While playing I have seen some errors, which I could not explain myself. I think, everything goes into the fact (as I mentioned before) that we try to deal with 2-nd level parametrization.
在玩的过程中,我看到了一些错误,我自己也无法解释。我认为,一切都源于我们尝试处理 2 级参数化的事实(正如我之前提到的)。
class FieldBinder<T> {
static class MyMap<M> extends HashMap<Class<M>, FieldBinder<M>> {
}
static final MyMap<?> instanceMap1 = new MyMap<Object>();
static final Map<Class<?>, FieldBinder<?>> instanceMap2 = new HashMap<Class<?>, FieldBinder<?>>();
public static <V> void test() {
Class<V> c1 = null;
FieldBinder<V> f1 = null;
Class<?> c2 = null;
FieldBinder<?> f2 = null;
instanceMap1.put(c1, f1); // error (see 1)
instanceMap1.put(c2, f2); // error (see 2)
instanceMap2.put(c1, f1); // ok
instanceMap2.put(c2, f2); // ok
instanceMap2.put(c1, f2); // wish to be an error, but ok
instanceMap2.put(c2, f1); // wish to be an error, but ok
}
}
回答by dma_k
The example you refer tells, how to recover the type (class) of object, while you need to recover the type (class) of parametrization. That is not possible.
您参考的示例说明如何恢复对象的类型(类),而您需要恢复参数化的类型(类)。这是不可能的。

