[英]In Java is it possible to create a type-safe Map of classes to instances of their class?
我想创建一个 map,它使用 class 作为键来返回该 class 的实例。 就像是:
<T> Map< Class<T>, T > instanceMap = new HashMap< Class<T>, T > ();
instanceMap.put( Boolean.class, Boolean.TRUE );
instanceMap.put( String.class, "asdf" );
instanceMap.put( Integer.class, 11 );
Boolean b = instanceMap.get( Boolean.class );
Integer i = instanceMap.get( Integer.class );
String s = instanceMap.get( String.class );
这可能吗? 我有一种感觉,不,这不是因为我不能指出T
是一个泛型类型,而不是一个名为“T”的 class。 感觉有点像“高阶泛型”。
编辑:我知道我可以尝试扩展 Map 并实现我自己的包装器等,但我特别询问是否仅使用 Java 的通用支持来执行此操作。 我对这个想法而不是这个特殊案例更感兴趣。
编辑2:如下所述,这是问题的重复(或更具体地说是子案例): Java map,其值受键的类型参数限制。 如果我能找到 eloquent 这样的措辞,我可能会找到答案,而不是发布这个。
你的意思是这样的?
public class Favorites {
private Map<Class<?>, Object> favorites =
new HashMap<Class<?>, Object>();
public <T> void setFavorite(Class<T> klass, T thing) {
favorites.put(klass, thing);
}
public <T> T getFavorite(Class<T> klass) {
return klass.cast(favorites.get(klass));
}
public static void main(String[] args) {
Favorites f = new Favorites();
f.setFavorite(String.class, "Java");
f.setFavorite(Integer.class, 0xcafebabe);
String s = f.getFavorite(String.class);
int i = f.getFavorite(Integer.class);
}
}
参见参考: Java map 值受键的类型参数限制
据我了解,您是说在创建此 map 之后,您想用类似...的内容填充它
f.put(String.class, "Hello");
f.put(Integer.class, new Integer(42));
f.put(x.getClass(), x);
等等对吧?
在那种情况下,我认为答案是否定的,你不能用 generics 做到这一点。 Generics 说,对于 class 的给定实例——在这种情况下是 map——您正在指定适用的类型。 所以如果你说new HashMap<String,Integer>;
,您是说针对此 map 的所有操作都将使用作为字符串的键和作为 integer 的值。 但这不是您在这种情况下想要做的。 您希望能够将任何类型的 object 放入 class,然后根据 object 的类型限制可接受的密钥类型。 这不是 generics 的工作方式。 它们不是彼此之间的关系,它们对于任何给定实例都是常数。
当然,您可以将这样的 map 创建为new HashMap<Class,Object>;
. 这不会强制 class 成为相应 object 的 class,但它允许您输入这些值。
除此之外,我认为你需要一个包装器。 我是否应该指出包装器的 put 只需要一个参数,因为它可能通过对其执行getClass()
来确定参数的 class,不需要告诉它?
在您的示例中,每个键/值的T
必须不同,而对于 generics,每个键/值的T
必须相同。 所以不,使用 generics 是不可能的。 (但当然可以通过强制转换和/或不使用泛型来实现)
JsonObject 可能是一个选项。 您可以将任何您喜欢的值作为 jsonobject 的值。 您需要的是 package org.json.JSONObject。 但是,您可能无法将 foreach 与 JSONObject 一起使用,但是有一些替代方法 如何迭代 JSONObject?
Map<T, U>
的点是 map T's to U's。 T 和 U 可以是任意的 class (假设没有通配符),但是一旦确定了就不能改变了。 在您的情况下,您想要一个根据您使用的键返回不同 class 的映射,这显然是不同的。
go 关于这个的通常方法是让 U Object
,因为你可以 go 提前并将它投射到你需要的任何东西。 但这当然破坏了 generics 应该提供的类型安全性。
简而言之,如果不编写某种包装器,我认为这是不可能的。
创建实例时, T
必须设置为某些特定类型,因此您无法使用put
方法向 map 添加不同的类型。 另一方面,泛型方法在调用它们时会设置其类型 arguments,从而允许您做您想做的事情。
Guava有一个ClassToInstanceMap类型,它使用通用方法来处理安全地将实例放入 map 并取出它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.