2010-01-07 40 views
3

爲什麼我會在這段代碼上遇到編譯時錯誤?Demystify通配符對我來說

public Interface Location { 
....... 
} 

類代碼...

Map<Type, List<? extends Location>> locationsTypeMap = new HashMap<Type, List<? extends Location>>(); 
    /** 
    Code to add elements to the hashMap. 
    */ 
    newLocation = getNewLocation() 
    while(mapHasElements){ 
    Location.Type key = location.getType(); 
    List<? extends Location> valueList = (List<? extends Location>)locationsTypeMap.get(key); //1 
    valueList.add(newLocation);/*Compile error*/ 
    } 

在另一方面,如果我更換步驟1中與線下它的工作原理

List<Location> valueList = (List<Location>)locationsTypeMap.get(key); 
+0

編譯器應該警告你投是不安全的,(名單)將編譯成(表),這不會拋出類強制轉換如果列表爲,則列表例外,如果您插入對象,則可能導致代碼其他部分出現類別轉換異常 – josefx 2010-01-08 00:14:07

回答

8

通配符 「?擴展位置」 是指「我希望它是List<T>對於某些T其中TLocation(或者是Location本身)的子類。「

現在,讓我們把它留在一邊。你會想到這編譯:

List<String> strings = new List<String>(); 
strings.add(new Object()); 

?我不這麼認爲 - 你不能將一個裸「對象」添加到字符串列表中。字符串列表中的任何項都必須是字符串。

回到你的第一件事。假設locationsTypeMap.get(key)返回一個對象(邏輯上 - 現在忽略類型擦除)a List<ExoticLocation> - 但假設newLocation實際上是BoringLocation的一個實例。您應該無法將BoringLocation添加到List<ExoticLocation>,並且編譯器知道這一點 - 所以它不會發生這種情況。

任何你從一個List<? extends Location>得到保證是某種形式的Location ...但你不能給它添加任何東西。與super相反:你不能保證你從List<? super Location>得到的任何東西都是Location,但你可以給它添加一個Location

給一個非常不同的例子:是一串香蕉水果的集合?那麼它在某種意義上說 - 任何你從它得到的一個水果。但它不是在另一個,因爲你不能添加任何舊的水果 - 如果你嘗試添加一個蘋果,它會脫落:)

請參閱Angelika Langer's Java Generics FAQ瞭解更多信息。

+0

感謝您的詳細解釋。 – 2010-01-07 23:50:55

-1

它可空類型,像這樣:

http://msdn.microsoft.com/en-us/library/1t3y8s4s%28VS.80%29.aspx

編輯:我一定是錯了,所以,鑑於以上兩個答案!抱歉!

+0

錯誤的語言,與空性無關。在C#中這將是完全不正確的語法。 – 2010-01-07 23:49:28

+0

我認爲在發佈和編輯之後,抱歉新堆棧溢出是我第一次在多語言論壇上發佈。 – deanvmc 2010-01-07 23:50:39