由于各种原因,我想将列表转换为数组,但Collection包含本身就是泛型的对象。
我已经尝试了以下四个选项来进行编译而无需 @supressWarnings('unchecked')注释,但它们都不起作用。是否有正确的解决方案,或者我被迫使用注释?
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()]);
答案 0 :(得分:12)
没有类型安全的方法来创建参数化类型的数组,例如Iterator<T>[]
。
或者,您可以创建原始数组:Iterator<?>[]
。或者,如果您可以完全避免使用数组,请使用类似List<Iterator<T>>
的集合类型。
不可能的原因是Java数组是协变的,并且Generic类型的参数化边界是不变的。也就是说:
Integer[] integers = new Integer[1];
Number[] numbers = integers; // OK because Integer extends Number
numbers[0] = new Double(3.14); // runtime exception
编译器允许分配,因为Double
扩展Number
,声明的numbers
类型为Number[]
。但是在运行时,实际的数组对象实例是原始的Integer[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<?>[]
在运行时知道它是一个包含Iterator
个元素的数组,<T>
中的Iterator<T>[]
被删除 at编译时,运行时无法知道它应该是什么。所以你得到一个未经检查的警告。