RFR(s): 8060192: Add default method Collection.toArray(generator)

Peter Levart peter.levart at gmail.com
Fri Dec 8 12:04:48 UTC 2017



On 12/08/2017 04:09 AM, David Lloyd wrote:
> Yes!  It would be even better for the "toArray(Class)" case if
> Class<T> had a "getArrayClass()" method which returned the Class<T[]>,
> which would allow:
>
>    return (T[]) Arrays.copyOf(elementData, size, componentType.getArrayClass());
>
> and similar for other array-backed collections.  I never understood
> why that method doesn't exist; in fact, am I wrong in understanding
> that "Array.newInstance(clazz, 0).getClass()" is effectively the only
> way to do this today?

I think there is a reason for Arrays.copyOf() to take an array type, not 
the component type. If it was taking component type, you could pass in 
primitive types too with no compile-time type checking, since int.class 
is of Class<Integer> static type. So why not the following:

public interface Collection<E> extends Iterable<E> {

     @SuppressWarnings("unchecked")
     default <T> T[] toArray(Class<T[]> arrayType) {
         return toArray((T[]) 
Array.newInstance(arrayType.getComponentType(), size()));
     }


ArrayList override could then simply be this:

     @Override
     public <T> T[] toArray(Class<T[]> arrayType) {
         return Arrays.copyOf(elementData, size, arrayType);
     }


Regards, Peter

>
> On Thu, Dec 7, 2017 at 7:03 PM, Martin Buchholz <martinrb at google.com> wrote:
>> (I'm still trying to love this new API)
>>
>> The changes to the jsr166 tck are fine.
>>
>> I'm not convinced that the new implementation for ArrayList is progress.
>> The current implementation of toArray(T[]) does
>>
>>              // Make a new array of a's runtime type, but my contents:
>>              return (T[]) Arrays.copyOf(elementData, size, a.getClass());
>>
>> which does not have to pay the cost of zeroing the array, so is potentially
>> faster.  (depends on whether the VM provides cheap pre-zeroed memory?! what
>> does jmh say?)
>>
>> If we're not getting type safety and not getting significantly better
>> performance, all we have is a more natural API.  But toArray(IntFunction)
>> also seems not very natural to me, and we'll have to live with the
>> toArray(new String[0]) wart forever anyways.  (But is it really so bad?)
>>   (Maybe toArray(Class<componentType>) is actually more natural?)
>>
>> On Thu, Dec 7, 2017 at 2:58 PM, Stuart Marks <stuart.marks at oracle.com>
>> wrote:
>>
>>> [Martin: please review changes to the JSR 166 TCK.]
>>>
>>> Another updated webrev for this changeset:
>>>
>>>      http://cr.openjdk.java.net/~smarks/reviews/8060192/webrev.2/
>>>
>>> This includes an override of toArray(IntFunction) in the implementation of
>>> Arrays.asList(), as requested by Tagir Valeev.
>>>
>>> Overrides are also added for various wrapper classes in j.u.Collections.
>>> Turns out there's a test test/jdk/java/util/Collections/Wrappers.java
>>> that checks to ensure that the wrappers don't inherit any default methods.
>>> (This has been a source of bugs in the past.)
>>>
>>> Significantly, this webrev also includes changes to several tests in the
>>> JSR 166 TCK. The issue is that these tests have cases for null handling,
>>> where they call
>>>
>>>      coll.toArray(null)
>>>
>>> to ensure that NPE is thrown. Given that this method is now overloaded:
>>>
>>>      toArray(T[])
>>>      toArray(IntFunction)
>>>
>>> passing null is now ambiguous and thus generates a compiler error. I've
>>> modified the tests to call toArray((Object[])null) which is a bit of a
>>> stopgap. I can't think of anything obviously better to do, though.
>>>
>>> s'marks
>>>
>
>



More information about the core-libs-dev mailing list