Use of super in type parameters

Zhong Yu zhong.j.yu at gmail.com
Wed Apr 17 17:11:50 PDT 2013


On Wed, Apr 17, 2013 at 4:53 PM, Martin Buchholz <martinrb at google.com> wrote:
> With the coming of lambda, it is more likely that people will be creating
> APIs with "not quite correct" generic types, as we are doing in

I believe that we can tweak generic signatures in APIs without
breaking calling codes. No API user really pays attention to all these
questions marks in a signature, he'll just go with instinct about
co/contravariances, deduced from the nature of the method, so his code
shouldn't break when the signature is changed for the better, because
the args he provides are all in the proper types.

For example, if a method signature is supposed to be
    <S super T> foo(List<S>, List<S>)
but we declare it today as, regrettably,
    foo(List<? super T>, List<? super T>)
we don't really expect users to supply List<S1> and List<S2> where
S1!=S2. If a user does that, it conflicts with the implicit/explicit
contract of the method, the type system couldn't help to catch the
mistake today, but it's a bug regardless.

Zhong Yu

> CompletableFuture.  Which is pretty bad for a feature that is designed
> specifically to provide compile time safety.  It would be nice to at least
> have an acknowledgment that there is a problem here, even if it will not be
> fixed for this release.
>
>
> On Mon, Apr 15, 2013 at 12:50 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
>>
>> I have encountered on stackoverflow.com several legit use cases of
>> lower bound. And the other day Ali Lahijani raised the question that
>> Stream.reduce(BinaryOperator) breaks convariance of Stream, and I
>> thought that the root problem is lack of lower bound - the method
>> would have had a better signature
>>     Stream<T>
>>         <U super T> Optional<U> reduce(BinaryOperator<U> accumulator)
>> So I don't think there's a lack of use cases for lower bound. (But I
>> have no idea how difficult it is to support it)
>>
>> Zhong Yu
>>
>>
>> On Mon, Apr 15, 2013 at 2:37 PM, Martin Buchholz <martinrb at google.com>
>> wrote:
>> > CompletableFuture currently has a method like this:
>> >
>> >     public CompletableFuture<Void> acceptEither
>> >         (CompletableFuture<? extends T> other,
>> >          Consumer<? super T> block) {
>> >         return doAcceptEither(other, block, null);
>> >     }
>> >
>> > But that signature is not quite correct (not as general as it could be).
>> >  The "correct" signature is
>> >
>> >     public <U super T> CompletableFuture<Void> acceptEither
>> >         (CompletableFuture<? extends U> other,
>> >          Consumer<U> block) {
>> >         return doAcceptEither(other, block, null);
>> >     }
>> >
>> > but that fails to compile, because type parameters can only be
>> > constrained
>> > by extends, not super.  Is implementing this on the radar?  Angelika
>> > claims
>> > "lower bounds for type parameters make no sense"
>> >
>> > http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#Why%20is%20there%20no%20lower%20bound%20for%20type%20parameters
>> > ?
>> >
>> > but I am finding that hard to believe.  Is she right? For comparison,
>> > the
>> > equivalent static method can be made to do what we want:
>> >
>> >     public static <U> CompletableFuture<Void> acceptEither
>> >         (CompletableFuture<? extends U> f,
>> >          CompletableFuture<? extends U> other,
>> >          Consumer<U> block) {
>> >         return ...
>> >     }
>
>


More information about the lambda-dev mailing list