2014-11-04 40 views
3

我有一個類MyStack<T>它定義了以下泛型類型及的toArrayMethod

public T[] toArray(){ 
    int s=size(); 
    @SuppressWarnings("unchecked") 
    T[] result=(T[])new Object[s]; 
    Node n=first; 
    for (int i=0; i<s; i++){ 
    result[i]=n.data; 
    n=n.next; 
    } 
    return result; 
} 

因爲這將返回T類型的數組,我會想,如果我宣佈這個例子:MyStack<String> s=new MyStack<>,那下面會完全有效:String[] test=s.toArray()。我認爲這是因爲sString的類型,toArray應該返回一個String類型的數組,因爲String已經基本上被這個類中的每個T代替(僅用於這個特定的實例,我知道)。這樣運行沒有錯誤的唯一方法是,如果我這樣做:Object[] test=s.toArray()

這是爲什麼?

回答

1

好吧,等一下。假設你的假設是正確的,String被替換爲每個T

以下演員陣容是否有效?

String[] result = (String[])new Object[s]; 

不,它不會。我們可以確定new Object[]不是String[]

現在有時你會看到類似(T[])new Object[n]的東西,但它只能用,因爲在泛型類中實際上變成了erased。 (這是一個欺騙性的成語。)

當類被編譯,實際發生的是,要T引用替換爲它的上限(可能Object,除非你有這樣的事情<T extends ...>):

public Object[] toArray(){ 
    int s=size(); 
    Object[] result=new Object[s]; 
    Node n=first; 
    for (int i=0; i<s; i++){ 
    result[i]=n.data; 
    n=n.next; 
    } 
    return result; 
} 

和演員移到調用點:

MyStack stack = new MyStack(); 
String[] arr = (String[])stack.toArray(); 

所以,事實上,雖然演員陣容在類中刪除,演員也曾經值類,其中ClassCastException拋出外面返回的情況發生。

無法實例化數組(通常是對象)通常是爲什麼Collections框架定義了將返回數組作爲參數的方法toArray。這對你一個簡單的版本是這樣的:

public T[] toArray(T[] inArray){ 
    int s = size(); 

    Node n = first; 
    for (int i = 0; i < s; i++){ 
     inArray[i] = n.data; 
     n = n.next; 
    } 

    return inArray; 
} 

有關如何一般創建陣列的一些想法,你可能會看到'How to create a generic array in Java?';但是你需要調用者傳遞一些參數給方法。

2

總之,輸入刪除。取自Java網站:

如果類型參數是無界的,則用普通類型的邊界或對象替換泛型類型中的所有類型參數。因此,生成的字節碼只包含普通的類,接口和方法。

這是什麼意思,當你的代碼被編譯時,MyStack<String>被編譯成MyStack<Object>。這是爲了確保泛型不會因需要創建新類而產生開銷。這如何適用於你?嗯..

MyStack<String> s = new MyStack<>(); 

轉換成..

MyStack<Object> s = new MyStack<>(); 

現在,這意味着當你調用toArray方法,即可以的唯一類型保證的廣告Object類型。編譯器無法確定它返回的所有內容都是String類型,所以它不會讓您將其視爲String,這是由於Java中的強類型。那麼,剩下的唯一變量類型是什麼?

Object[] array = s.toArray(); 

額外的閱讀

+0

'因爲擦除'實際上並不回答這裏的問題。它只能解釋爲什麼這個例外是從一個奇怪的地方拋出的。 – Radiodef 2014-11-04 19:41:47

+0

我想我有點困惑。如果我們能做的最好的就是說's'是一個堆滿了'Objects'的堆棧,所有其他的類都是從這個堆棧中下來的,爲什麼還要使用泛型呢?我在這裏錯過了什麼? – user50210 2014-11-05 05:22:33

+0

@ user50210問題是,您正試圖將'Object []'強制轉換爲'String []'並且它不是一個有效的強制轉換。 – Radiodef 2014-11-05 16:48:34