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