1

In the wikipedia article about co- and contravariance there is an example use case and then an explanatory sentence describing what the type declaration means. I find this extremely useful. After reading the explanation a few times, I feel that I understand what it says.

<T extends Comparable<? super T>> T max(Collection<T> coll);

The bounded wildcard ? super T conveys the information that max calls only contravariant methods from the Comparable interface.

Can somebody explain in a similar language, what the type declaration on the of the andThen() function in the java.util.function.Consumer @FunctionalInterface means:

public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {

e.g.

The bounded wildcard ? super T conveys the information that andThen .... ?


And I have a secondary question: How can I find out myself, what such a type declaration means? E.g. in first example above from the java.util.Collections util class: How are the type bounds of a class - T - able to convey information about what the methods of T are doing? Can anybody point me to the relevant paragraphs in the Java language specification for this?

Pfiver
  • 249
  • 2
  • 6
  • 1
    Last question is a duplicate of [this](http://stackoverflow.com/questions/19488357/why-is-t-bounded-by-object-in-the-collections-max-signature). – shmosel Mar 14 '17 at 23:01
  • 1
    And [this](http://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super) might answer the rest. – Jorn Vernee Mar 14 '17 at 23:04
  • 1
    The word is "grok", not "grock". – Lew Bloch Mar 14 '17 at 23:19
  • Ok, thanks for the link shmosel. I removed the last question, as it is indeed answered there already. However, for the first question it would be great to get the blanks filled in and I would love to get a pointer to the relevant part of the Java Language Spec for the second question. Thanks for the spelling aid Lew. – Pfiver Mar 14 '17 at 23:25

1 Answers1

0

Possible answer to the first question:

public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {

The bounded wildcard ? super T conveys the information that andThen takes Consumers of T or supertypes of T, aka. contravariant Consumers, as arguments.


Possible answer to the secondary question: https://stackoverflow.com/a/2501513

Basically - completely independent of generics (!) - method return return types are inherently "covariant" (assumed to be "producers") in the Java language. If overriding a method in a child class, you can always declare a more specific return type.

Method arguments are of course also "covariant" - you can only pass more specific objects than the method signature specifies. But on subclasses, although the method is technically not overriden for non-parametric arguments - adhering to the Liskov_substitution_principle - it often makes sense to declare "contravariant" argument types in child classes, which - if the name and other arguments are equal - "overloads" the methods in the parent class. "Static" (reference-type-governed) method dispatch will then ensure that the (less specific) child method is called wins. Method arguments are assumed to be "consumed" and then PECS applies. Anyhow, for generic parameters, bridge methods are generated and it is all a bit more hairy. But we will get there.

Community
  • 1
  • 1
Pfiver
  • 249
  • 2
  • 6