我想创建一个使用类作为键来返回该类实例的映射。类似的东西:
<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”的类。感觉就像是“高阶泛型”。
编辑:我知道我可以尝试扩展Map并实现我自己的包装器等,但我特别要求使用Java的通用支持来做这件事。我对这个想法更感兴趣而不是这个特例。
编辑2:如下所述,这是问题的重复(或更具体地说是子案例):Java map with values limited by key's type parameter。如果我能够找到那样雄辩的措辞,我可能会找到答案而不是发布这个。
答案 0 :(得分:13)
你的意思是这样的吗?
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);
}
}
答案 1 :(得分:3)
据我了解,您说在创建此地图后,您希望使用类似的内容填充它...
f.put(String.class, "Hello");
f.put(Integer.class, new Integer(42));
f.put(x.getClass(), x);
等。正确?
在这种情况下,我认为答案是否定的,你不能用泛型来做到这一点。泛型说,对于类的给定实例 - 在这种情况下的映射 - 您指定适用的类型。因此,如果您说new HashMap<String,Integer>;
,则表示针对此映射的所有操作都将使用一个字符串键和一个整数值。但在这种情况下,这不是你想要做的。您希望能够将任何类型的对象放入类中,然后根据对象的类型约束键的可接受类型。这不是泛型如何工作。它们不是彼此之间的关系,对于任何给定的实例它们都是常数。
当然,您可以创建new HashMap<Class,Object>;
这样的地图。这不会强制类成为相应对象的类,但它允许您输入这样的值。
除此之外,我认为你需要一个包装器。我是否应该指出包装器的put只需要一个参数,因为它可能通过对它进行getClass()
来确定参数的类,没有必要告诉它?
答案 2 :(得分:1)
在您的示例中,T
对于每个键/值必须不同,而对于泛型,T
对于每个键/值必须相同。所以不,使用泛型这是不可能的。 (当然,实现当然可以使用转换和/或不使用泛型)
答案 3 :(得分:0)
Map<T, U>
的要点是将T'映射到U'。 T和U可以是任何类(假设没有通配符),但一旦确定,它们就不能改变。在您的情况下,您希望映射根据您使用的密钥返回不同的类,这显然是不同的。
通常的做法就是制作U Object
,因为你可以继续把它投射到你需要的任何东西上。但是,这当然打破了仿制药应该提供的类型安全性。
简而言之,如果不编写某种包装,我认为这是不可能的。
答案 4 :(得分:0)
T
设置为某种特定类型,因此您无法使用put
方法向地图添加不同类型。另一方面,通用方法在调用它们时设置了它们的类型参数,允许你做你想做的事。
Guava有ClassToInstanceMap类型,它使用通用方法来处理安全地将实例放入地图并将其删除。
答案 5 :(得分:0)
JsonObject可能是一个选项。 您可以将任何您喜欢的内容作为jsonobject的值。你需要的是包org.json.JSONObject。但是,您可能无法将foreach与JSONObject一起使用,但有一些替代方法How to iterate over a JSONObject?