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