RFR(s): 8160406: Collection.toArray() spec should be explicit about returning precisely an Object[]

Stuart Marks stuart.marks at oracle.com
Thu Nov 30 02:54:20 UTC 2017



On 11/29/17 5:20 PM, Martin Buchholz wrote:
> Thanks.  This looks good, and finishes the effort started 12 years ago.  
> Apologies for not having made this spec change myself years ago.
> 
> I tried to find a less JLSese way to wordsmith it.  Nearby spec talks about the 
> "runtime type" of the array. Maybe s/component/runtime component/ but I'm not 
> sure that's actually better.

Good point. I looked through the specs of both toArray() methods to see if 
anything needed to be fixed up. Indeed, there is.

Off-list, Claes Redestad pointed out that in the T[] method, there is the following:

      * @param <T> the runtime type of the array to contain the collection

This is in fact completely wrong. The array type is T[] and so T is not the type 
of the array, it's the component type. Furthermore, it's not the runtime 
component type, it's the static component type. This is pretty easy to 
illustrate. Suppose we have:

     var list = List.of("a")
     CharSequence[] csa = list.toArray((CharSequence[])new String[0])

In the second line, the type variable T is CharSequence, but the runtime 
component type of the returned array is String. (Alternatively, the runtime type 
of the array is String[].)

The specs here need to distinguish between the array's type and the array's 
component type, and also between the static component type and the runtime 
component type. It just goes to show that nothing is ever as simple as it seems!

Here's what I did:

* In a couple places, I substituted "runtime component type" and also made this 
be a link to the Class.getComponentType() method to make sure it's absolutely 
clear what's being talked about. The JLS describes the "element type" of an 
array and sometimes the "component" of an array; I chose "component type" 
because it's consistent with Class.getComponentType().

* I fixed up the @param <T> doc to be "static component type".

* I fixed up ArrayStoreException in the T[] method because it confused the 
array's type with the Collection elements' runtime types. I mirrored the wording 
from JLS 10.5 ArrayStoreException, which is framed around assignment compatibility.

I left some statements that mentioned the "runtime type of the array" because I 
think they're correct as they stand. For example, "...a new array is allocated 
with the runtime type of the specified array...."

Revised patch appended below. Overall it's not much bigger than the previous 
patch, but it did require a lot of close reading.

Thanks,

s'marks





diff -r 9bb771005928 -r fb5434478123 
src/java.base/share/classes/java/util/Collection.java
--- a/src/java.base/share/classes/java/util/Collection.java	Tue Nov 28 17:14:30 
2017 -0800
+++ b/src/java.base/share/classes/java/util/Collection.java	Wed Nov 29 18:30:35 
2017 -0800
@@ -268,7 +268,8 @@
       * Returns an array containing all of the elements in this collection.
       * If this collection makes any guarantees as to what order its elements
       * are returned by its iterator, this method must return the elements in
-     * the same order.
+     * the same order. The returned array's {@linkplain Class#getComponentType
+     * runtime component type} is {@code Object}.
       *
       * <p>The returned array will be "safe" in that no references to it are
       * maintained by this collection.  (In other words, this method must
@@ -278,7 +279,8 @@
       * <p>This method acts as bridge between array-based and collection-based
       * APIs.
       *
-     * @return an array containing all of the elements in this collection
+     * @return an array, whose {@linkplain Class#getComponentType runtime component
+     * type} is {@code Object}, containing all of the elements in this collection
       */
      Object[] toArray();

@@ -315,14 +317,14 @@
       * Note that {@code toArray(new Object[0])} is identical in function to
       * {@code toArray()}.
       *
-     * @param <T> the runtime type of the array to contain the collection
+     * @param <T> the static component type of the array to contain the collection
       * @param a the array into which the elements of this collection are to be
       *        stored, if it is big enough; otherwise, a new array of the same
       *        runtime type is allocated for this purpose.
       * @return an array containing all of the elements in this collection
-     * @throws ArrayStoreException if the runtime type of the specified array
-     *         is not a supertype of the runtime type of every element in
-     *         this collection
+     * @throws ArrayStoreException if the runtime type of any element in this
+     *         collection is not assignable to the {@linkplain 
Class#getComponentType
+     *         runtime component type} of the specified array
       * @throws NullPointerException if the specified array is null
       */
      <T> T[] toArray(T[] a);


More information about the core-libs-dev mailing list