1. ホーム
  2. java

[解決済み] Javaで汎用配列を作成する方法は?

2022-03-16 09:15:17

質問

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;
}

でも、本当に何が起こっているのかわからないんです。

どうすればいい?

お返しに質問なんですが、あなたの GenSet checked"またはunchecked"ですか? これはどういう意味ですか?

  • チェック済み : ストロングタイピング . 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];
        }
    
        ...
    }
    
    

消去法で実装されているため、quot;generic" クラスは実行時にどの型引数で生成されたかを知らないので、何らかの明示的なメカニズム(型チェック)を実装しない限り型安全性を提供することができないのです。