2013-07-19 11 views
8

私はJavaでArray.newInstance()T[]ではなくObjectを返すことに気付きました。このメソッドは、Javaがジェネリック型をサポートする前に導入されているため、理解できます。Array.newInstanceの汎用バージョンはありますか?

しかし、これと同等の汎用バージョンが存在しないことは驚きです。 Java 7のArrays.copyOfは同じではありません。新しいダミー配列(すべてのヌルオブジェクトが内部にある)を作成するのではなく、パラメータの内容をコピーします。

これの実装は些細なようですが、それをJREに追加しない理由はありますか?または私はちょうど1つを見つけることができませんか?

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にはない一般的なヘルパーを提供したのは初めてのことではありません。

あなたはこれを知っているかもしれませんが、将来的にこの問題を抱えるgooglerの背景については: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 []'を必要とするので、型パラメータではなく追加パラメータが必要です。私は 'Class 'や 'T []'を受け入れる 'Arrays.newInstance'をなぜ使うことができないのか不思議に思っています(テンプレートとしてのみ、内容は無視されます)。 –

+0

はい、私は理解しますが、あなたは決してうまくいかないあなたのニーズにAPIを曲げようとしています;)私はこれがイライラすることができますが、それはそれが方法であることを認めます。 – pstanton

+0

ジェネリック型を書くとき、私はこのコンストラクタへの引数として具体的なパラメータ型を渡すことがよくあります。 – pstanton

3

Array.newInstance()<T> T[] newInstance(Class<T> class, int size)のように宣言できないという基本的な理由は、プリミティブの配列を作成するために使用できるからです。例えば、Class<Integer>int.classを渡した場合、宣言からInteger[]オブジェクトを返すと予想されます。ただし、実際にはint[]オブジェクトが返されますが、サブタイプはInteger[]ではないため、型が間違っています。

確かに、彼らは、プリミティブ型を禁止newReferenceArrayInstance()ような追加のメソッドを追加することができ(プリミティブ型を渡されたときに、例えば、例外をスロー)、従って安全T[]を返すように宣言することができます。しかし、これは、チェックされていないキャストを避けるために完全に冗長なメソッドを追加するようなものです。

関連する問題