ジェネリックを使用して、型の安全性を維持しながら、探している型の配列を正確に取得する方法を次に示します (Object
配列を返すか、コンパイル時に警告が表示される他の回答とは対照的に)。
import java.lang.reflect.Array;
public class GenSet<E> {
private E[] a;
public GenSet(Class<E[]> clazz, int length) {
a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));
}
public static void main(String[] args) {
GenSet<String> foo = new GenSet<String>(String[].class, 1);
String[] bar = foo.a;
foo.a[0] = "xyzzy";
String baz = foo.a[0];
}
}
これは警告なしでコンパイルされ、 でわかるように、 asmain
のインスタンスを宣言する型が何であれ、その型の配列に割り当てることができ、その型の変数に要素を割り当てることができます。つまり、配列は配列内の値は正しい型です。GenSet
a
a
Java チュートリアルで説明されているように、クラス リテラルをランタイム タイプ トークンとして使用することで機能します。クラス リテラルは、コンパイラによって のインスタンスとして扱われますjava.lang.Class
。使用するには、クラス名の後に.class
. そのため、クラスを表すオブジェクトString.class
として機能します。これは、インターフェイス、列挙型、任意次元の配列 (例: )、プリミティブ (例: )、およびキーワード(例: ) に対しても機能します。Class
String
String[].class
int.class
void
void.class
Class
それ自体はジェネリックです ( として宣言されClass<T>
、T
はオブジェクトが表す型をClass
表します)。つまり、 の型はString.class
ですClass<String>
。
したがって、コンストラクタ for を呼び出すときは常に、インスタンスの宣言された型のGenSet
配列を表す最初の引数にクラス リテラルを渡します (たとえば、 for )。プリミティブは型変数に使用できないため、プリミティブの配列を取得できないことに注意してください。GenSet
String[].class
GenSet<String>
コンストラクター内でメソッドを呼び出すと、メソッドが呼び出されたオブジェクトによって表されるクラスにキャストされcast
た渡された引数が返されます。で static メソッドを呼び出すと、最初の引数として渡されたオブジェクトによって表される型と、2 番目の引数として渡された によって指定された長さの配列として返されます。メソッドを呼び出すと、メソッドが呼び出されたオブジェクトによって表される配列のコンポーネント タイプを表すオブジェクトが返されます (たとえば、オブジェクトが配列を表していない場合) 。Object
Class
newInstance
java.lang.reflect.Array
Object
Class
int
getComponentType
Class
Class
String.class
String[].class
null
Class
その最後の文は完全に正確ではありません。を呼び出すと、 class を表すオブジェクトString[].class.getComponentType()
が返されますが、その型はではなくです。そのため、次のようなことはできません。Class
String
Class<?>
Class<String>
String foo = String[].class.getComponentType().cast("bar"); // won't compile
オブジェクトClass
を返すすべてのメソッドについても同様です。Class
この回答に対するJoachim Sauer のコメント(自分でコメントするほどの評判はありません) については、キャストを使用する例T[]
では警告が表示されます。その場合、コンパイラは型の安全性を保証できないためです。
Ingo のコメントに関する編集:
public static <T> T[] newArray(Class<T[]> type, int size) {
return type.cast(Array.newInstance(type.getComponentType(), size));
}