Java ジェネリックの実装により、次のようなコードは作成できません。
public class GenSet<E> {
private E a[];
public GenSet() {
a = new E[INITIAL_ARRAY_LENGTH]; // Error: generic array creation
}
}
型の安全性を維持しながらこれを実装するにはどうすればよいでしょうか?
Java フォーラムで次のような解決策を見つけました:
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
どうしたの?
ベストアンサー1
代わりに質問します。GenSet
「チェック済み」ですか、それとも「チェックなし」ですか? それはどういう意味ですか?
チェック済み:強い型付け。
GenSet
含まれるオブジェクトの型を明示的に認識します (つまり、コンストラクタが引数で明示的に呼び出されClass<E>
、メソッドに型以外の引数が渡されると例外がスローされます)E
。Collections.checkedCollection
。-> その場合は、次のように記述します。
public class GenSet<E> { private E[] a; public GenSet(Class<E> c, int s) { // Use Array native method to create array // of a type only known at run time @SuppressWarnings("unchecked") final E[] a = (E[]) Array.newInstance(c, s); this.a = a; } E get(int i) { return a[i]; } }
未チェック:弱い型付け。引数として渡されたオブジェクトに対して、実際には型チェックは行われません。
-> その場合は次のように書く必要があります
public class GenSet<E> { private Object[] a; public GenSet(int s) { a = new Object[s]; } E get(int i) { @SuppressWarnings("unchecked") final E e = (E) a[i]; return e; } }
配列のコンポーネント型は消去型パラメータの:
public class GenSet<E extends Foo> { // E has an upper bound of Foo private Foo[] a; // E erases to Foo, so use Foo[] public GenSet(int s) { a = new Foo[s]; } ... }
これらすべては、Java のジェネリックの既知の意図的な弱点から生じています。ジェネリックは消去を使用して実装されているため、「ジェネリック」クラスは実行時にどの型引数を使用して作成されたかがわからず、したがって、明示的なメカニズム (型チェック) が実装されない限り、型の安全性を提供できません。