簡短回答:沒有(據我所知)。
這裏的問題是,你所做的事在Java中根本不是類型安全的。看看這個例子:
import java.util.*;
class ClassCast {
public static void main(String[] args) {
HashMap<String, Pair<?, ?>> map = new HashMap<>();
map.put("test", new Pair<String, Integer>("Hello", 5));
Pair<Double, Double> pair = (Pair<Double, Double>) map.get("test");
}
}
class Pair<T,V> {
T a;
V b;
Pair(T a, V b) {
this.a = a;
this.b = b;
}
}
你可能會認爲這裏ClassCastException
,但它編譯和運行完全正常。原因在於Pair<String, Integer>
和Pair<Double, Double>
的實際類別實際上只是Pair
(類型擦除之後)。
爲了獲得類型安全,您必須實現「Typesafe heterogeneous container pattern」(由Josh Bloch在Effective Java中詳細解釋)。簡而言之,您必須將類型參數包含在地圖的關鍵字中。根據您的需要,您可能可以直接使用類作爲密鑰,否則可能必須創建關鍵對象。
實現示例:
public class CacheManager {
private Map<MultiKey, Cache<?,?>> cacheMap = new HashMap<>();
@SuppressWarnings("unchecked")
public <T,V> Cache<T,V> get(String name, Class<T> t, Class<V> v) {
// Type-safe since types are encoded in key(i.e. map will not
// return something with the wrong type), and key is type-checked
// on insertion.
return (Cache<T,V>) cacheMap.get(new MultiKey(name, t, v));
}
public <T,V> void put(String name, Class<T> t, Class<V> v, Cache<T,V> cache) {
cacheMap.put(new MultiKey(name, t, v), cache);
}
class MultiKey {
Object[] keys;
Integer hash = null;
MultiKey(Object... keys) {
this.keys = keys;
}
@Override
public int hashCode() {
if (hash == null) hash = Arrays.hashCode(keys);
return hash;
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof MultiKey)) return false;
return Arrays.equals(keys, ((MultiKey) o).keys);
}
}
}
用法示例:
CacheManager mng = new CacheManager();
mng.addCache("SI", String.class, Integer.class, new Cache<String, Integer>());
Cache<String, Integer> cache = mng.getCache("SI", String.class, Integer.class);
System.out.println(cache);
這不是很漂亮,但它實際上是類型安全的。儘管它可以根據實際情況進行改進,所以您不應該按原樣使用此代碼。例如,如果您可以從緩存對象中獲取類型,則不需要addCache
中的類參數。
沒有未經檢查的強制轉換(在這種特殊情況下將是類型安全的IMO),沒有辦法做到這一點。您可以通過向通配符添加邊界來添加更多類型安全。 – 2015-03-31 11:56:35
是否有通配符類型,因爲單個CacheManager實例將存儲許多不同類型的緩存? (也就是說,爲什麼它不是CacheManager?) –
2015-03-31 12:07:45
Rohit你可以舉例說明如何向通配符添加更多邊界。我現在正在做明確的轉換(Cache)cacheManager.getCache(「test」)Erik你是對的我有不同的緩存,所以我不能在泛型中使用CacheManager。請提出更好的建議。 –
user1927808
2015-03-31 12:28:40