2013-08-27 48 views
0

我想實現Map接口,但將K和V綁定到接口)。但是,考慮到Java集合API,特別是MAP接口至少會限制方法參數,請使用Object而不是通用類型K和V.例如,接口指定:public boolean containsValue(Object value)而不是public boolean containsValue(V value)。在這種場合我不能依靠編譯器類型的安全性。爲Map實現強制類型參數的屬性(如接口中)

需要明確的是,我要實現類似如下:

class MyMap< K , V extends ValueInterface> implements Map<K,V>

不過,我需要實現類似於下面的方法:

@Override 
public boolean containsValue(Object value) { 
     // What to do here? 
     ValueInterface v = (ValueInterface) v; 
     v.getWhatIWant().andDoThing(); 
     // Follow on... 
} 

哪些選項和/或在這種情況下我有最佳做法?

+0

你的第二個陳述是什麼意思? –

+0

這個問題有一些有趣的答案,爲什麼'Map'接口不使用通用類型的某些方法參數:http://stackoverflow.com/questions/857420/what-are-the-reasons-why-map-getobject關鍵不是完全通用的 – andersschuller

+0

@RohitJain我編輯了這個問題。希望它更好地知道。但是代碼舉例說明,由於接口契約,我必須處理一個對象,但我希望V確信我有可能依賴於ValueInterface屬性。 – fabiim

回答

1

這是Map的接口合同 - 因此您必須按照原樣執行合同。

不過,我認爲有兩個原因,爲什麼Map這部分的設計是一件好事:

i)本Mapcontract是,你可以在下列情況下得到的映射值:

如果此映射包含從密鑰k到值v的映射,使得 (key == null?k == null:key.equals(k)),則此方法返回v; 否則返回null。如果此映射包含指定鍵的映射關係

返回true:(可以有至多一個這樣的映射。)

或等價,而具體到你的問題有關containsKey(Object key)。更正式地說,當且僅當此映射包含關鍵字k的映射(key == null?k == null:key.equals(k))時才返回true。 (可以有至多一個這樣的映射。)

這樣,你不關心打字,而是平等

II)這是真的只是同一個點,但考慮到以下幾點:

Map<String, Integer> map = new HashMap<>(); 
String key = "A Key"; 
Integer value = 1; 
map.put(key, value); 

Object objectKey = key; // this is the same key object, but it is typed as Object 
map.containsKey(objectKey); // what would you want/expect this to return? 
map.get(objectKey); // ...or this? 

因此,對於您的實現的Map,我不會建議只是鑄造Object鍵(你會得到一個運行時異常...)。你決定如何實現它取決於你的設計。讓我們設想一下,你在保存類型列表中的鍵和值...然後你會被告知鑄造前檢查instanceofObject鍵:

public boolean containsKey(Object key) { 
    if (key instanceof K) { 
    // do your thing... 
    } else { 
    return false; 
    } 
} 

注意instanceof檢查基礎對象的類型,而不是其聲明的類型,所以:

String key = "A Key"; 
Object objectKey = key; 
boolean isString = (objectKey instanceof String); // is true 

真的,我會建議,而不是詢問如何給力的東西,違背了合同Map,你要會問這個問題"why is the contract that way?」 ......

+0

我有這樣的感覺,因爲基於平等的實現契約是這樣的。這對我來說聽起來很糟糕,因爲它看起來像讓實現細節逃到了界面的設計中。但是,在這個問題的具體背景下,我真的不關心這個決定背後的原因。我只想知道我是否應該:避免實現Map或者通過cast來解決這個問題(小心使用instanceof off course)或者其他一些我不知道的通用魔法。 – fabiim

+1

@fabiim - Map接口中的這​​種設計是一件好事(你應該關心它,因爲理解它爲什麼是好東西會更好地使你能夠在Java中使用泛型)。 Java泛型沒有任何魔力 - 它們是該語言中非常有用的一部分,儘管這需要一些時間和精力來學習/理解。至於你的特定用法,這一切都取決於你想要達到的目標......目前你的原始問題是「我想實現Map接口...」,對此(不出意外)你需要實現地圖界面。 – amaidment

0

如果你想要實現Map<K,V>你將被要求實現接口中的所有方法。

你可以擴展AbstractMap<K,V>並覆蓋抽象方法,再加上您要自定義行爲的任​​何非抽象方法(只要你不違反合同Map)。

+0

因此,本質上,你的答案是:那麼,除了投射外,你什麼都不能做並希望更好(如果你想實施地圖):) – fabiim

+0

不幸的是,是的。 'Map'接口最初是在泛型之前設計的,我想更改簽名會破壞現有的代碼。 –

相關問題