小编典典

ArrayList.toArray()中的Java泛型

java

假设您有一个arraylist定义如下:

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

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

String someLine = someData.get(0);

而且编译器完全知道它将得到一个字符串。是的仿制药!但是,这将失败:

String[] arrayOfData = someData.toArray();

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


阅读 264

收藏
2020-12-03

共1个答案

小编典典

如果你看一下执行toArray(T[] a)的ArrayList
类,它是这样的:

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代表什么。换句话说 在Java中不允许
创建非可校正类型的数组
JLS§4.7)。


数组存储异常
JLS§10.5)中的另一个重要报价:

如果数组的组件类型不可修改(第4.7节),则Java虚拟机将无法执行上一段所述的存储检查。
这就是为什么禁止使用不可修改元素类型的数组创建表达式的原因(第15.10.1节)。

这就是Java提供重载版本的原因toArray(T[] a)

我将重写toArray()方法以告诉它它将返回E数组。

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

无法从Java
Doc
创建类型参数的实例可能对您也很有趣。

2020-12-03