繁体   English   中英

在 Java 中,是否可以为其 class 的实例创建一个类型安全的 Map 类?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM