Java map,key = class,value =该类的实例

我不确定我想做什么是可能的,但如果是的话,我想知道如何做。 基本上,我想创建一个Map,其中键是一个类( java.lang.Class ),该条目的值是该类的一个实例。 目前我有

 private Map<Class, Object> myMap = new HashMap<Class, Object>(); 

但是,这意味着任何Object都可以放在Map中。 如果可能的话,我想制作它,因此只有键中类的一个实例可以放在地图中。 有没有办法使用? 对Class进行参数化以确保这一点?

此外,我发现在做这样的事情时可能会有内存泄漏 。 我不确定我是否完全理解这是怎么发生的。 我只会将单个对象粘贴到地图中,那么是否仍会出现内存泄漏问题? 如果是这样,我该如何预防呢?

Java的类型系统根本不足以强制执行您直接描述的类型约束,并且您需要执行一些不安全的转换以使其工作 – 或者将Map包装在其他强制类型安全的API中。 Guava的 ClassToInstanceMap正是为了这个用例,它提供了一个外部安全的API,它对Map接口施加了额外的限制以使其工作。 (披露:我向番石榴捐款。)

这可能导致内存泄漏的唯一时间是,如果您在此处使用的某些类在应用程序的生命周期内不会保留。 对于许多用户来说,这不是一个问题,特别是如果您正在编写一个“服务器端”应用程序而不关心卸载未使用的类。

您可以隐藏集合,只允许通过访问器方法访问它。

 private final Map myMap = new HashMap(); public  void putMap(Class tClass, T t) { myMap.put(tClass, t); } @SuppressWarnings("unchecked") public  T getMap(Class tClass) { return (T) myMap.get(tClass); } 

警告可以忽略,因为您知道即使编译器没有,最后一个方法中的强制转换也是安全的。

您使用的是异构容器 。 通过使用类型令牌(如您所做)和Class.cast()以及正确的应用程序逻辑,可以使这些类型安全:因此在Class.cast()有一个未经检查的suppressWarning,但应用程序逻辑保证了正确性。

我建议你阅读Josh Bloch的Effective Java Item 29:考虑类型安全的异构容器。 他的榜样是:

 // Typesafe heterogeneous container pattern - implementation public class Favorites { private Map, Object> favorites = new HashMap, Object>(); public  void putFavorite(Class type, T instance) { if (type == null) throw new NullPointerException("Type is null"); favorites.put(type, instance); } public  T getFavorite(Class type) { return type.cast(favorites.get(type)); } } 

如果您持有任意实际不再需要的许多不同类型,我只会看到内存泄漏的可能性。

由于类型擦除,这是不可能的。

但是,您可以将HashMap子类化并将一些逻辑写入put方法,该方法将为您执行此操作:

 public void put(K key, V value) { if ( // value is an instance of key using .getClass()) { super.put(key, value) } throw new Exception(); } 

(仅供参考的代码)

我有同样的要求。 我使用下面的代码解决了它:

 interface Service { } class ServiceCache { private HashMap, Service> services; public ServiceCache() { services = new HashMap<>(); } public  T getService(Class service) { if (services.containsKey(service)) return (T) services.get(service); return null; } public  void addService(T service, Class serviceInterface) { services.put(serviceInterface, service); } }