9

さまざまな理由から、リストを配列に変換したいのですが、コレクションにはそれ自体がジェネリックであるオブジェクトが含まれています。

@suppressWarnings('unchecked')アノテーションを必要とせずにコンパイルするために、次の 4 つのオプションを試しましたが、どれも機能しません。これを正しく機能させるための解決策はありますか、それとも注釈を使用する必要がありますか?

Iterator<T>[] iterators;
final Collection<Iterator<T>> initIterators = new ArrayList<Iterator<T>>();

// Type safety: Unchecked cast from Iterator[] to Iterator<T>[]
iterators = initIterators.<Iterator<T>>toArray(
        (Iterator<T>[])new Iterator[initIterators.size()]);

// Type safety: Unchecked invocation toArray(Iterator[]) of the generic 
// method toArray(T[]) of type Collection<Iterator<T>>
// Type safety: The expression of type Iterator[] needs unchecked conversion 
// to conform to Iterator<T>[]
iterators = initIterators.<Iterator<T>>toArray(
        new Iterator[initIterators.size()]);

// Type safety: The expression of type Iterator[] needs unchecked conversion 
// to conform to Iterator<T>[]
iterators = initIterators.toArray(new Iterator[initIterators.size()]);

// Doesn't compile
iterators = initIterators.toArray(new Iterator<T>[initIterators.size()]);
4

1 に答える 1

12

などのパラメータ化された型の配列を作成するタイプ セーフな方法はありませんIterator<T>[]

または、生の配列を作成することもできます: Iterator<?>[]. または、配列の使用を完全に回避できる場合は、 のようなコレクション型を使用しますList<Iterator<T>>

それが不可能な理由は、Java 配列が共変であり、ジェネリック型のパラメーター化された境界が不変であるためです。つまり、次のようになります。

Integer[] integers = new Integer[1];
Number[] numbers = integers; // OK because Integer extends Number
numbers[0] = new Double(3.14); // runtime exception

DoubleextendsNumberと宣言された型がnumbersisであるため、コンパイラは割り当てを許可しますNumber[]。しかし、実行時には、実際の配列オブジェクト インスタンスはオリジナルInteger[1]であり、配列は含まれるオブジェクトの型を認識しています。

ジェネリックでは、パラメーター化された型が異なります。1 つは、コンパイル時の型の消去により、実行時の型を本質的に認識していないことです。

List<Integer> integerList = new ArrayList<Integer>();

List<Number> numberList = integerList; // compiler error, prevents:
numberList.add(new Double(3.14)); // would insert a Double into integerList

Collection<Integer> integerCollection = integerList; // allowed
// OK because List extends Collection and the <type parameter> did not change

Collection<Number> numberCollection = integerList; // compiler error
// an "Integer" is a "Number"
// but "a collection of Integers" is more specific than "a collection of Numbers"
// and cannot be generally treated the same way and guarantee correct behavior

List<?> rawList = integerList; // allowed, but...
rawList.add(new Integer(42));  // compiler error, Integer is not a ... a what?

ジェネリックを使用すると、Java では、(ランタイムではなく) コンパイラーに依存して、ジェネリック型が正しく安全であることを検証します。

そのため、要素Iterator<?>[]を含む配列であることは実行時に認識されますが、 inはコンパイル時に消去され、ランタイムは本来の配列を知る方法がありません。したがって、チェックされていない警告が表示されます。Iterator<T>Iterator<T>[]

于 2013-05-19T03:58:26.410 に答える