2012-12-07 58 views
1

keySet()返回java.util.Set。 爲什麼不投射到NavigableSet拋出ClassCastException? 這可能是真實的Object是一個帶有java.util.Set引用的TreeSet。我無法理解這一點。爲什麼不投射到NavigableSet拋出ClassCastException?

import java.util.*; 
class A1{} 
public class Main{ 
    public static void main(String args[]){ 
     SortedMap nvs=new TreeMap(); 
     nvs.put(1,"one"); 
     nvs.put(2,"two"); 
     nvs.put(3,"three"); 
     nvs.put(4,"four"); 
     NavigableSet nss=(NavigableSet)nvs.keySet(); 
     for(Object ob: nss){ 
       System.out.print(nvs.get(ob)+", "); 
     } 
    } 
} 

回答

2

做的最好的事情是看的TreeMap實際的代碼(這是從Java 1.7):

public Set<K> keySet() { 
    return navigableKeySet(); 
} 

public NavigableSet<K> navigableKeySet() { 
    KeySet<K> nks = navigableKeySet; 
    return (nks != null) ? nks : (navigableKeySet = new KeySet(this)); 
} 

而這裏的KeySet類聲明:

static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {...} 

,你可以請參見TreeMap#keySet方法返回類型Set,該類型是NavigableSet的超級接口。從它返回的參考Set指向KeySet實例,如navigableKeySet()方法。

而且由於KeySet類實現了NavigableSet,所以您始終可以將指向其實例的引用轉換爲NavigableSet引用。

只是爲了確保你是獨立的keySet()方法實現,你可以簡單地調用navigableKeySet()方法來獲取NavigableSet,避免投

+0

+1顯示實際來源:) – PermGenError

+0

也許你可能還補充說'KeySet'是'TreeMap'類內的'static final class',它實現了'NavigableSet'接口。這將完成你的答案。 –

+0

@RohitJain謝謝,也加了這個。 –

0

它不會通過ClassCastException因爲返回的對象是一個NavigableSet。例如,您可以在返回的對象上使用getClass()方法並打印它。這個類是NavigableSet或它的一個子類。

您也可以使用調試器(例如Eclipse)來獲取對象的類。

因爲SortedMap.keySet()規範告訴它返回一個Set對象,所以將它轉換爲NavigableSet可能並不安全。其他或實施變更可能導致您的代碼通過ClassCastException

編譯器無法檢查這一點,因此檢查在運行時執行。

+1

你怎麼知道的? –

+0

我編輯了我的答案。否則,你會碰到一個ClassCastException –

+0

這可能是,但Java規範告訴它它返回java.util.Set。 –

2

你的問題表明,你不明白多態性。讓我們用一個類比。你去酒吧,要一杯啤酒。你得到一個斯特拉。你沒有特別要求斯特拉,而且酒吧沒有公佈他們的啤酒實際上是斯特拉啤酒,但事實是,你得到的實際,具體類型的啤酒是斯特拉。由於酒吧並不能保證當你要啤酒時會得到Stella,所以你不應該依賴它,因爲酒吧的未來版本可能會給你一個Jupiler,因爲Jupiler和Stella都是啤酒。

這與你的問題一樣。返回類型是Set,所以它可以返回任何類型的Set。除非javadoc保證方法實際上返回一個NavigableSet,否則不應該依賴它。

+1

+1這整個發臭的東西。很好的例子來解釋這個;)哈哈,這也是週末。 –

+0

我不同意),我瞭解多態性,我明白它可以是任何類型的Set,但我想知道它是哪一種)正如你在我的問題中看到的,我認爲它可以是一個TreeSet,它是一個NavigableSet),我是部分正確的。 –

+0

那麼你爲什麼認爲TreeSet是NavigableSet接口的唯一可能的實現?如果你完全理解多態性,你會知道一個接口可以有多個實現。 –

相關問題