繁体   English   中英

Java map,键 = class,值 = class 的实例

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

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