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

Martin Buchholz martinrb at google.com
Thu Nov 30 03:28:06 UTC 2017


Wordsmithing is hard.  Which may be why I never tried to improve these
specs decades ago.

I would make one change.

+     * @param <T> the static component type of the array to contain the
collection

Just drop runtime/static

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

the "static" is "obvious" and the caller could in theory provide the T to
use.


On Wed, Nov 29, 2017 at 6:54 PM, Stuart Marks <stuart.marks at oracle.com>
wrote:

>
>
> 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/ja
> va/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