[英]Java map, key = class, value = instance of that class
我不确定我想做什么是可能的,但如果是的话,我想知道怎么做。 基本上,我想创建一个 Map,其中键是 class ( java.lang.Class
),该条目的值是该 class 的一个实例。目前我有
private Map<Class<?>, Object> myMap = new HashMap<Class<?>, Object>();
但是,这意味着任何Object都可以放在Map中。如果可以的话,我想制作它,所以只有密钥中的class的实例可以放在map中。有什么办法可以使用吗? 对 Class 进行参数化以确保这一点?
另外,我发现做这样的事情时可能会发生memory 泄漏。 我不确定我是否完全理解这是怎么发生的。 我只会将 singleton 对象粘贴到 map 中,所以仍然会担心 memory 泄漏吗? 如果是这样,我该如何预防?
Java的类型系统根本不足以强制执行您直接描述的类型约束,并且您需要执行一些不安全的转换以使其工作 - 或者将Map
包装在其他强制类型安全的API中。 Guava的 ClassToInstanceMap
正是为了这个用例而提供的,它提供了一个外部安全的API,它对Map
接口施加了额外的限制以使其工作。 (披露:我向番石榴捐款。)
这可能导致内存泄漏的唯一时间是,如果您在此处使用的某些类在应用程序的生命周期内不会保留。 对于许多用户来说,这不是一个问题,特别是如果您正在编写一个“服务器端”应用程序而不关心卸载未使用的类。
您使用的是异构容器 。 这些可以通过使用类型令牌进行类型安全(因为你已经这样做)和Class.cast()
与正确的应用逻辑:所以有内选中suppressWarning Class.cast()
但应用程序逻辑保证正确性。
我建议你阅读Josh Bloch的Effective Java Item 29:考虑类型安全的异构容器。 他的榜样是:
// Typesafe heterogeneous container pattern - implementation
public class Favorites {
private Map<Class<?>, Object> favorites =
new HashMap<Class<?>, Object>();
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
}
如果你持有你实际上不再需要的任意多种不同的类型,我只会看到内存泄漏的可能性。
您可以隐藏集合,只允许通过访问器方法访问它。
private final Map<Class, Object> myMap = new HashMap<Class, Object>();
public <T> void putMap(Class<T> tClass, T t) {
myMap.put(tClass, t);
}
@SuppressWarnings("unchecked")
public <T> T getMap(Class<T> tClass) {
return (T) myMap.get(tClass);
}
警告可以忽略,因为您知道即使编译器没有,最后一个方法中的强制转换也是安全的。
由于类型擦除,这是不可能的。
但是,您可以将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<Class<? extends Service>, Service> services;
public ServiceCache() {
services = new HashMap<>();
}
public <T extends Service> T getService(Class<T> service) {
if (services.containsKey(service))
return (T) services.get(service);
return null;
}
public <T extends Service> void addService(T service, Class<? extends Service> serviceInterface) {
services.put(serviceInterface, service);
}
}
clazz.isInstance(TypeClass.class)
可用于比较类型。 根据文档public native boolean isInstance(Object obj)
方法
确定指定的 Object 是否与此 Class 表示的 object 分配兼容。此方法是 Java 语言instanceof运算符的动态等效项。 如果指定的 Object 参数不为 null,并且可以强制转换为此 Class object 表示的引用类型,而不会引发 ClassCastException,则该方法返回 true。 否则返回 false。
clazz.isAssignableFrom(TypeClass.class)
可用于比较超类型和子类型。 根据文档public native boolean isAssignableFrom(Class<?> cls)
方法
确定 class 或此 Class object 表示的接口是否与 class 或由指定的 Class 参数表示的接口相同,或者是其超类或超接口。 如果是,则返回 true; 否则返回 false。 如果这个 Class object 表示原始类型,如果指定的 Class 参数正好是这个 Class object,则此方法返回 true; 否则返回 false。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.