2012-11-14 58 views
3

我有一個自定義的地圖到字符串方法。它旨在用於任何種類的具有String鍵的Map,不限於某些特定的地圖值類型。例如,映射值可能來自javax.jms.Message.getObjectProperty(String name)方法,或者只是普通的字符串。什麼是定義地圖的正確方法<String, ?>方法參數

以下哪項是最適合使用的方法簽名,以及爲什麼或者都是平等的?

String map2String(Map<String, Object> map){...} 

String map2String(Map<String, ?> map){...} 

String map2String(Map<String, ? extends Object> map){...} 

或(添加編輯)

<E> String map2String(Map<String, ? extends E> map){...} 

或其他什麼東西?

而且,該方法包含for-each循環有點像這樣:

for(Entry<String, ?> entry : map.entrySet()) { 
    String key = entry.getKey(); 
    String value = entry.getValue().toString(); 
} 

哪個是「正確」的類型爲entry變量,它的問題(除的?不相容組合在地圖,Object在入口類型中)。

回答

5

String map2String(Map<String, ?> map){...}是正確的(? extends Object是多餘的)

第一個將無法工作,因爲你不能就能夠調用

Map<String,Integer> myMap = {...} 
map2String(myMap); // Map<String,Integer> is not Map<String,Object> 

正確的類型爲entry變量是Entry<String, ?>你嫌。

+0

...看起來像正確的答案,具有贊成票和沒有不同意見。在接受之前等一會兒。 – hyde

1

最好的方法是使用第一個例子,而不是你發佈的Object使用你的類類型。否則,您必須強制轉換對象到其他類或使用instanceof,這不是好主意

String map2String(Map<String, YourClass> map){...} 

關於其他的:

String map2String(Map<String, ? extends Object> map){...}

嘛,? extends Object是不是因爲得到的每一類的最佳選擇(亞型)從Object? extends Object?之間沒有區別。

class MyClass extends RootClass 
.... 
class YourClass extends RootClass 
.... 
String map2String(Map<String, ? extends RootClass> map) // this method can fetch argumets by type of Map `MyClass` and `YourClass`. 

進一步:

String map2String(Map<String, ?> map){...} 

比方說,你用String map2String(Map map){...}沒有任何類型的

extends通配符您可以在如果情況使用。編譯器會告訴你: 映射是一個原始類型。對泛型地圖的引用應參數化爲。但你懶得想想女巫參數。我看到很多次,人們輸入如:String map2String(Map<?,?> map){...}刪除警告。但其糟糕的做法。

+0

這是用於轉儲任何映射的字符串鍵,toString()用於值,所以沒有比'Object'更具體的類型。我會澄清這個問題。 – hyde

+0

@hyde所以使用'E'類型:String map2String(Map map){...}這個quizzical短語'?擴展E'意味着它也可以用集合中的所有成員添加任何類型的子類型爲E的元素。(但是,您必須聲明您的類/接口爲''的通用類型) –

+0

是否使用了' ... '簡單地使用''帶來什麼優勢?在這種情況下,我看不到任何東西。 – hyde

0

處理集合我會選擇繼承和泛型作爲原則。

舉例來說,我將聲明一個接口,或一個抽象基類並將其傳遞作爲收集類型參數,像:

public abstract class AnimalBaseClass { 
    //... 
    public abstract void makeSound(); 
} 

public interface AnimalInterface { 
    public void makeSound(); 
} 

然後收集會變成要麼Map<String, AnimalInterface>Map<String, ? extends AnimalBaseClass>。這樣,第一張地圖將接受實現AnimalInterface的任何類,第二張地圖將接受抽象基類AnimalBaseClass的任何子類,如Dog extends AnimalBaseClass

至於有關定義列表答案就在Java泛型,即繼承原則wildtypes你的問題:List<Integer>不是List<Number>一個亞型,但List<Integer>List<? extends Integer>List<? extends Number>一個亞型。所以,如果你有List<Integer> liList<Number> ln你不能等於ln = li。但是,如果您聲明lnList<? extends Number> ln該公式將是有效的。但是請不要忘記,雖然公式是有效的,但將Numbers添加到列表中將導致編譯時錯誤,如ln.add(new Float()),因此您的引用將更像是「只讀」版本的內容。

所以,你的泛型方法將變成:

public <T extends YourBaseClass> String map2String(Map<String, T> map) { 
    //do something with your map and return a String object 
} 

而且,如果你想Object成爲你的基類,只是省略「extends YourBaseClass」。

相關問題