2011-08-17 131 views
2

假設我有一類排序:的Java Collections.synchronizedMap()的複雜類型定義

public class MyMap<K, V> implements Map<Set<K>, V> { 
    ... 
} 

,我想能夠執行它的同步。一種方法是在內部同步這些方法(可能與同步的關鍵字),但如果我打算將它用於更一般的用法,那麼使用外部同步可能會更好,也許使用Collections.synchronizedMap()方法。

問題出現在我嘗試實現這個類:假設我有下面的類:

public class Foo { 
    MyMap<String, Object> _myMap; 
    public Foo() { 
    _myMap = Collections.synchronizedMap(new MyMap<String, Object>()); 
    } 
} 

在課程的第4行,我得到的錯誤「類型不匹配:不能從地圖轉換<設置< String>,Object>到MyMap < String,Object>「。 Eclipse建議我執行以下兩項操作之一:向MyMap < String,Object>添加強制轉換或將_myMap的類型更改爲Map < Set < String>,Object>。然而,我顯然不想做後者,因爲使用MyMap而不是Map的全部意義在於,我可以利用MyMap中實現的附加功能。然後,當我嘗試添加演員,因爲他們建議,使該行現在看起來像

_myMap = (MyMap<String, Object>) Collections.synchronizedMap(new MyMap<String, Object>); 

我收到以下錯誤,當代碼實際上執行:

java.lang.ClassCastException: java.util.Collections$SynchronizedMap cannot be cast to ****.MyMap 

看來,synchronizedMap ()將MyMap向下轉換爲其「真」類型,即地圖<設置< String>,Object >>,然後不允許將它轉換回MyMap,這是我傳入的同步映射()。

有什麼辦法可以破解synchronizedMap來處理這種類嗎?如果不是,可能會推薦實現外部或同步的方法?

也許作爲一個後續問題,這種實現接口的方法是類型參數不是簡單類型(例如第一個Map參數中的非平凡集合K>在實際中常用的接口)?實現類(本例中的MyMap)是否可以使用除簡單類型以外的任何其他參數進行參數化 - 換句話說,即使有人正在實施像Map< Set< K>, V>這樣的實現類,實施類是否也可以具有其他類型的東西,而不是其它類型的實例類型:< K,V>參數(儘管有其他未使用的參數)?

在一個完全無關的方面說明,沒有人知道我怎樣才能繞過奇怪的標籤捕捉(這樣我就不必像「Map < K,V>」那樣放置空格),即使當我把它與塊?

+1

MyMap是做什麼HashMap,TreeMap,LinkedHashMap不?爲什麼你需要一個特定的類而不是標準的Map接口? –

+0

爲什麼'Foo'有'MyMap'的構造函數?它應該是一個'Foo'構造函數嗎? –

+0

忽必烈 - 很好的接收,我的錯字。 JB Nizet - 如果你真的想知道,有一個原因,地圖的關鍵是設置 - 我以前的問題中的一個可能會爲那些好奇:)的人更多的光。當然,如果Java SDK或谷歌Guava Collections中的任何現有地圖都達到了類似的目的,我會用它們來代替,而不是試圖創建一個新的地圖。 – omnilinguist

回答

1

問題是,您正在將您的字段定義爲「我的地圖」。如果您打算使用外部同步,那麼您只能使用Map,而且以後您甚至不能投射到MyMap。

原因是SynchronizedMap實際上不會爲您的類「添加」同步,而是返回一個新的Map實現,同步,將您傳遞的地圖實例作爲參數封裝。

2

如果您查看Collections.synchronizedMap的javadoc(請參閱here),那麼您將看到實際應該如何使用它以及它的功能。要注意的主要問題是,你傳遞的Map包裝在一個新的Map同步實現中,這個實現和MyMap不一樣,所以這就是顯式轉換失敗的原因。

至於解決你的問題,我不是100%肯定你正在尋找,但將一個簡單的ConcurrentHashMap是不夠的?看看javadocs的here