为什么允许heap.toArray(new int [0] [0])?

时间:2019-02-23 21:31:53

标签: java heap

我看到了这样的代码:

public int[][] test() {
       Queue<Integer> queue = new PriorityQueue<>();
       //Do Something 
       return queue.toArray(new int[0][0])
}

我很好奇最后一行,为什么这里允许int[0][0]queue.toArray方法的参数不应该是Array恢复到的内存吗?

2 个答案:

答案 0 :(得分:2)

toArray的文档在这里: https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html#toArray(T[])

toArray的签名是<T> T[] toArray(T[] a)。 因此,编译器推断T = int[]。 请注意,集合的类型参数是E,而不是T

无论代码打算做什么,很可能会失败,因为文档说:

  

抛出:ArrayStoreException-如果指定的运行时类型   数组不是此元素中每个元素的运行时类型的超类型   集合

int[]不是Integer的超类型。

答案 1 :(得分:2)

  

queue.toArray方法的参数不应该是Array恢复到的内存吗?

不一定。

发生的事情是,toArray方法计算出容纳集合内容所需的大小数组。如果提供的数组足够大,则将在其中写入内容。否则,将分配并使用一个新数组。在后一种情况下,参数数组的实际类型确定分配的数组的类型。


如@ReputationFarmer所述,在这种情况下,queue.toArray(new int[0][0])可能会给出运行时异常(ArrayStoreException)。呼叫应该是 queue.toArray(new Integer[0])

之所以不会产生编译错误,是因为此toArray方法的类型签名为<T> T[] toArray(T[] a),它允许将 any 数组类型作为论点。


那么...为什么他们用这种方式定义toArray

答案是Java的历史:

  • toArray API中指定了Collection方法,该API已在Java 1.2中添加到Java。

  • 从Java 1.2到Java 1.4.2,此方法的签名为:

    public Object[] toArray(Object[] a)
    

    换句话说,您可以传递任何引用类型的数组,编译器会接受它。

  • 他们在Java 5中引入了泛型,并重新定义了toArray方法以使其具有当前签名。

我怀疑他们没有重新定义toArray签名的原因是:

    <T extends E> T[] toArray(T[] a)

对于某些在较早版本中有效的Java代码,它将中断(产生编译错误)。