2013-07-19 50 views
8

我注意到,在Java Array.newInstance()返回Object,而不是T[]。這是可以理解的,因爲這種方法是在Java支持泛型類型之前引入的。是否有任何通用版本的Array.newInstance?

然而,這是一個驚喜,沒有相應的通用版本。 Java 7的Arrays.copyOf是不一樣的 - 它複製參數的內容,而不是創建一個新的虛擬數組(內部都是空對象)。

由於這樣的實現看起來微不足道,有沒有任何理由不將它添加到JRE中?或者我找不到一個?

UPDATE

看來我必須提供我自己的「瑣碎」的實施,以阻止問題的誤解。

class MyArrayUtil { 
    //Generic version for classes 
    @SuppressWarnings("unchecked") 
    public static <T> T[] newArrayOf(T[] t, int len){ 
     return (T[]) Array.newInstance(t.getClass().getComponentType(), len); 
    } 
    //For array of int 
    public static int[] newArrayOf(int[] t, int len){ 
     return new int[len]; 
    } 
    //For other primitive types... 
} 

我不會發布此代碼作爲答案,因爲它不是問題的答案。問題是出於原因和/或現有代碼,而不是如何實施。

UPDATE

我已經更新了代碼,使其類似於Arrays.copyOf,人和的優勢是程序員可以簡單地改變參數的類型來調整代碼爲另一種類型。此外,我還取消了原始類型的使用Array.newInstance

+0

不,不可能以編譯時安全的方式實現它。例如,你不能創建一個新的實例:'List []'。編譯器永遠不會知道'T'的類型是什麼,所以它不能保證客戶端代碼是安全的。 – Muel

+0

由於'Arrays.copyOf'可以完成這項工作,所以沒有明顯的原因你不能。 –

+2

'Arrays.copyOf'確定要複製的數組的具體類型。 – pstanton

回答

7

番石榴提供just such a function。不管是什麼原因,Guava(或Apache Commons)都不是第一次提供JDK沒有的常用助手。

您可能已經知道這一點,但對於將來出現這種情況的谷歌讀者會有一些背景:簽名不能通用的原因是方法Array.newInstancereturned Object in Java 1.4,因此爲了向後兼容,原始版本的方法也應該返回Object。若是已經泛型爲:

<T> T[] newInstance(Class<T> componentType, int length) 

...然後返回類型是Object[],不Object。這將打破向後兼容性,Java設計人員一直非常努力地不去做。

Arrays.copyOf方法只與Java 1.6一起出現,因此不必擔心向後兼容性。

+0

現在我想我明白爲什麼'newArray'支持原始類型沒有什麼意義。如果你想創建一個非泛型類型參數的新數組,你可以簡單地使用'new XYZ []'。如果不是這種情況,你必須使用類類型,只有在這種情況下,'newArray'設施纔有用。 –

+0

您仍然必須將該類型作爲參數傳遞... – pstanton

+0

如果您在方法簽名/類定義中需要類似的參數/字段,則不應該出現問題。 –

4

不,你需要以某種方式作爲參數傳遞具體類型。正如你所提到的,Arrays.copyOf表明了這一點。

Class<T> type = determinteTheTypeSomehow(); 
return (T[]) Array.newInstance(type, length); 
+0

'Array.newInstance'需要'Class ',因爲'Arrays.copyOf'需要'T []',所以它們確實需要額外的參數而不是類型參數。我只是想知道爲什麼我們不能有一個'Arrays.newInstance'接受'類'或'T []'(僅作爲模板;內容被忽略)。 –

+0

是的,我明白了,但你試圖將api屈從於你永遠不會工作的需求;)我承認,這可能令人沮喪,但這是它的方式。 – pstanton

+0

當我編寫泛型類型時,我經常將具體參數類型作爲參數傳遞給構造函數以實現此(和其他)目的。 – pstanton

3

Array.newInstance()不能被聲明爲<T> T[] newInstance(Class<T> class, int size)的根本原因是因爲它可以用來創建基元數組。因此,例如,如果您通過int.class(其類型爲Class<Integer>),則從聲明中可以預料它會返回Integer[]對象。但是,該函數實際返回一個int[]對象,該對象不是Integer[]的子類型,因此它具有錯誤的類型。

當然,他們可以(當傳遞基本類型例如拋出異常),並因此可以安全地被聲明爲返回T[]增加一個額外的方法等newReferenceArrayInstance()禁止原始類型。但是,這似乎是增加了一個完全冗餘的方法,僅用於避免未經檢查的轉換。

相關問題