ArrayList.toArray() 中的 Java 泛型

标签 java arrays generics

假设你有一个如下定义的数组列表:

ArrayList<String> someData = new ArrayList<>();

稍后在您的代码中,由于泛型,您可以这样说:

String someLine = someData.get(0);

并且编译器完全知道它将得到一个字符串。耶泛型!但是,这将失败:

String[] arrayOfData = someData.toArray();

toArray() 将始终返回一个对象数组,而不是定义的泛型。为什么get(x)方法知道返回的是什么,而toArray()却默认是Objects?

最佳答案

如果你看一下 ArrayList<E>toArray(T[] a) 的实现类,是这样的:

public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

此方法的问题是您需要传递相同泛型类型的数组。现在考虑如果此方法不带任何参数,那么实现将类似于:

public <T> T[] toArray() {
    T[] t = new T[size]; // compilation error
    return Arrays.copyOf(elementData, size, t.getClass());
}

但这里的问题是,你不能在 Java 中创建泛型数组,因为编译器不知道 T 到底代表什么。换句话说,创建不可具体化类型的数组(JLS §4.7)在 Java 中是不允许的

Array Store Exception (JLS §10.5) 的另一个重要引述:

If the component type of an array were not reifiable (§4.7), the Java Virtual Machine could not perform the store check described in the preceding paragraph. This is why an array creation expression with a non-reifiable element type is forbidden (§15.10.1).

这就是为什么 Java 提供了重载版本 toArray(T[] a) .

I will override the toArray() method to tell it that it will return an array of E.

因此,您应该使用 toArray(T[] a),而不是覆盖 toArray()

Cannot Create Instances of Type Parameters来自 Java Doc 的内容可能对您来说也很有趣。

关于ArrayList.toArray() 中的 Java 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36598928/

相关文章:

java - 如何检查 String 是否包含 Java 中的右组括号

javascript - 在 Javascript 中,为什么在 .join() 中删除了\b 个字符?

ios - 遍历 NSArray 工作......有时

generics - Kotlin强制参数类型为字符串, bool 值或数字

generics - OCaml 中的参数化

java - 有没有办法在Java中检测Mac OS或Windows OS是否处于暗模式

java - 从 Scanner 和 JOptionPane 加载的字符串之间的区别

java - 如何将自动时间戳表条目从纪元时间更改为现在?

arrays - 如何在结构中初始化数组

java - 泛型 Java 8 上的调用方法