I saw a code like this:
public int[][] test() {
Queue<Integer> queue = new PriorityQueue<>();
//Do Something
return queue.toArray(new int[0][0])
}
I'm curious about the last line, why is int[0][0]
allowed here? Shouldn't the argument to the queue.toArray
method be the memory that Array restored into?
The documentation of toArray
is here: https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html#toArray(T[])
toArray
's signature is <T> T[] toArray(T[] a)
. So the compiler infers T = int[]
. Note that the collection's type parameter is E
, not T
.
Whatever this code intended to do, most likely it fails, since documentation says:
Throws: ArrayStoreException - if the runtime type of the specified array is not a supertype of the runtime type of every element in this collection
And int[]
is not a supertype of Integer
.
Shouldn't the argument to the queue.toArray method be the memory that Array restored into?
Not necessarily.
What happens is that the toArray
method works out what size array is needed to hold the collection contents. If the supplied array is large enough, then that is where the contents are written. Otherwise a new array is allocated and used. In the latter case, the argument array's actual type determines the type of array that is allocated.
As @ReputationFarmer notes, in this case queue.toArray(new int[0][0])
will probably give a runtime exception ( ArrayStoreException
). The call should be queue.toArray(new Integer[0])
.
The reason that this doesn't give a compilation error is that the type signature of this toArray
method is <T> T[] toArray(T[] a)
which allows any array type to be passed as an argument.
So ... why did they define toArray
that way?
The answer is in the history of Java:
The toArray
methods are specified in the Collection
API which was added to Java in Java 1.2.
From Java 1.2 to Java 1.4.2, the signature for this method was:
public Object[] toArray(Object[] a)
In other words, you could pass an array of any reference type, and the compiler would accept it.
In Java 5, they introduced generics, and redefined the toArray
method to have its current signature.
I suspect that the reason that they didn't redefine the toArray
signature to be:
<T extends E> T[] toArray(T[] a)
is that it would break (give compilation errors) for some Java code that was valid with earlier releases.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.