Both Collector.of() are not correctly typed

Stuart Marks stuart.marks at oracle.com
Thu Dec 6 02:26:56 UTC 2018


Hi Rémi,

I can sponsor this for you. Can you file a bug report?

Thanks,

s'marks

On 11/25/18 12:10 PM, Remi Forax wrote:
> ping !
> 
> Rémi
> 
> ----- Mail original -----
>> De: "Remi Forax" <forax at univ-mlv.fr>
>> À: "core-libs-dev" <core-libs-dev at openjdk.java.net>
>> Envoyé: Mardi 13 Novembre 2018 15:47:54
>> Objet: Both Collector.of() are not correctly typed
> 
>> Last year,
>> a student of mine as remarked that the two variants of Collector.of() are not
>> correctly typed (the wildcards are missing)
>> and obviously, this year it's one of my teaching assistant that has found
>> exactly the same issue.
>> So let's fix this issue.
>>
>> Adding the wildcards is both source and binary backward compatible in this case
>> - the methods of are static (so no overriding possible)
>> - the wildcards types are super types of the types of current version, so it
>> will not break at use sites and
>> - the erased signature is the same so it's a binary backward compatible change.
>>
>> The right code is
>>     @SuppressWarnings("unchecked")
>>     public static<T, R> Collector<T, R, R> of(Supplier<? extends R> supplier,
>>                                               BiConsumer<? super R, ? super T> accumulator,
>>                                               BinaryOperator<R> combiner,
>>                                               Characteristics... characteristics) {
>>         Objects.requireNonNull(supplier);
>>         Objects.requireNonNull(accumulator);
>>         Objects.requireNonNull(combiner);
>>         Objects.requireNonNull(characteristics);
>>         Set<Characteristics> cs = (characteristics.length == 0)
>>                                   ? Collectors.CH_ID
>>                                   :
>>                                   Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
>>                                                                            characteristics));
>>         return new Collectors.CollectorImpl<>((Supplier<R>)supplier, (BiConsumer<R,
>>         T>)accumulator, combiner, cs);
>>     }
>> and
>>     @SuppressWarnings("unchecked")
>>     public static<T, A, R> Collector<T, A, R> of(Supplier<? extends A> supplier,
>>                                                  BiConsumer<? super A, ? super T> accumulator,
>>                                                  BinaryOperator<A> combiner,
>>                                                  Function<? super A, ? extends R> finisher,
>>                                                  Characteristics... characteristics) {
>>         Objects.requireNonNull(supplier);
>>         Objects.requireNonNull(accumulator);
>>         Objects.requireNonNull(combiner);
>>         Objects.requireNonNull(finisher);
>>         Objects.requireNonNull(characteristics);
>>         Set<Characteristics> cs = Collectors.CH_NOID;
>>         if (characteristics.length > 0) {
>>             cs = EnumSet.noneOf(Characteristics.class);
>>             Collections.addAll(cs, characteristics);
>>             cs = Collections.unmodifiableSet(cs);
>>         }
>>         return new Collectors.CollectorImpl<>((Supplier<R>)supplier, (BiConsumer<R,
>>         T>)accumulator, combiner, (Function<A, R>)finisher, cs);
>>     }
>>
>> You may ask why the code is safe given there are now some
>> @SuppressWarnings("unchecked"), it's because for a functional interface,
>> the parameter types are contra-variant and the return type is covariant.
>>
>> At one point in the future, perhaps JEP 300 [1] will be implemented, in that
>> case we will be able to remove the @SuppressWarnings.
>>
>> You may also notice that, we may want at the same time  replace the
>> unmodifiableSet(EnumSet.of() + add) with Set.of(),
>> i've not done that change given it's not related to the typing issue.
>>
>> cheers,
>> Rémi
>>
>> [1] https://openjdk.java.net/jeps/300


More information about the core-libs-dev mailing list