2015-10-26 95 views
0

我正在爲我的Java期中學習,但在實現類型方面存在一些問題。這裏有一個錯誤的類,但我不明白爲什麼。有人可以幫助我,也許給我一些解釋?當然,錯誤與實體類型有關。Array and reified type

class Conversion { 
    public static <T> T[] toArray(Collection<T> c) { 
     T[] a = new T[c.size()]; 
     int i = 0; 
     for (T x: c) a[i++] = x; 
     return a; 
    } 
} 
+0

簡單的答案是,你不能創建的項目類型從未來的數組一個類型參數。 – biziclop

回答

4

數組是一個具體化類型。這意味着數組的確切類型在運行時是已知的。因此,在運行時,例如,String[]Integer[]之間存在差異。

這不是泛型的情況。泛型是一個編譯時構造:它們用於在編譯時檢查類型,但在運行時確切類型不再可用。在運行時,類型參數只是Object(或者如果類型參數具有上限,則爲上限)。所以在運行時,Collection<String>Collection<Integer>的類型沒有區別。

現在,當您想創建一個類型參數的數組時,會出現問題。在運行時,不知道什麼是T,所以如果你編寫new T[10],Java運行時不知道要創建什麼類型的數組,String[]Integer[]。這就是爲什麼你不能以這種方式創建一個數組。

有幾個解決方法,其中沒有一個是完全令人滿意的。通常的解決方法是創建一個Object[],並把它轉換到你想要的類型的數組:

T[] theArray = (T[]) new Object[size]; 

但是,你要記住,這是非常不安全的。如果創建的箭頭的範圍很小,則只應該執行此操作,以便您可以手動確保該陣列僅包含T實例,並且永遠不會將其分配給任何無法實現的實例。下面的代碼演示了此問題:

public class Foo<T extends Comparable> {  
    T[] createArray() { 
     return (T[])new Object[1]; 
    } 

    public static void main(String... args) { 
     Foo<String> foo = new Foo<>(); 
     String[] ss = foo.createArray(); // here 
    } 
} 

標有此行拋出一個異常,因爲你想投的Object[]String[]

如果你真的需要一個正確的運行時類型的數組,你需要使用反射。獲取某個類型的令牌,你需要的類型(類型Class<T>的),並使用Array.newInstance(type, cize)創建陣列,例如:

public T[] createArray(Class<T> type, int size) { 
    return (T[]) Array.newInstance(type, size); 
} 
+0

哇!非常感謝你 :) – Francesco

2

您不能創建一個泛型類型的數組。編譯器可能會抱怨像「通用數組創建」。有這周圍沒有很好的方法,但有一個辦法做到這一點:

public static <T> T[] toArray(Class<T> type, Collection<T> c) { 
    T[] a = (T[]) Array.newInstance(type, c.size()) 
    … 
} 

你需要Class<T>這一點,但它的工作:)

+0

那麼究竟做什麼類類型? – Francesco

+1

'類'是類型'T'的類,就像'類'是'String'的類一樣。 'Array.newInstance'需要明確的引用它,'T.class'將不起作用,因爲'T'本身是不可確定的,所以'toArray'的調用者需要提供它。 – akaIDIOT

+0

非常感謝你 – Francesco

3

Reifiable type由JLS定義:

A型是reifiable當且僅當如下條件之一成立:

  • 它指的是一個非通用類或接口類型聲明。
  • 它是一個參數化類型,其中所有類型參數都是無界通配符(§4.5.1)。
  • 它是一種原始類型(§4.8)。
  • 它是一種原始類型(§4.2)。
  • 它是一個數組類型(§10.1),其元素類型是可調整的。
  • 它是一個嵌套類型,其中對於由「。」分隔的每個類型T,T本身是可賦值的。

參見下面§4.7音符,推理很詳細的描述。

您的類型參數不屬於上述內容,因此無法確定。因而不能在array creation expression使用:

它是一個編譯時間錯誤,如果ClassOrInterfaceType並不表示 一個reifiable類型(§4.7)。否則,ClassOrInterfaceType可能會命名爲 任何指定的引用類型,即使是抽象類類型(§8.1.1.1)或 接口類型。

相關問題