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