java - 如何安全地将泛型类型的 Collection 转换为数组?

标签 java generics

<分区>

出于各种原因,我想将列表转换为数组,但是 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()]);

最佳答案

没有类型安全的方法来创建参数化类型的数组,例如 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

编译器允许赋值,因为 Double延伸Numbernumbers 的声明类型是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>[]在编译时被删除,运行时无法知道它应该是什么。所以你会得到一个未经检查的警告。

关于java - 如何安全地将泛型类型的 Collection 转换为数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16630359/

相关文章:

java - 如何在不依赖 Pivotal GemFire 缓存的情况下启动 Spring Boot 应用程序

java - 在java中使用数组作为switch case语句

ios - Swift - 如何用不同类型的枚举声明变量/函数?

ios - 两个用 NSIndexPath 填充的通用数组的补充/交集

java - 如何动态设置textview的边距?

java - 如何覆盖 Ivy 缓存的位置?

java - java中的String有长度限制吗?

c# - NSubstitute 模拟泛型方法

generics - Swift 语言中具有自定义对象的通用类型

java - 原始类型将 super 传递给 sub