簡體   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