Dibro
Dibro

Reputation: 65

Double super wildcard

In this code I have an error on the second line while the first one successfully compiles:

Comparator<? super Integer> a = (x, y) -> Integer.compare(x, y);
Comparator<? super Integer> b = a.thenComparing((x, y) -> Integer.compare(x, y));

The error is "incompatible types: Object cannot be converted to int"

thenComparing has following signature: thenComparing(Comparator<? super T> other), so as I understand other in this context will become something like Comparator<? super super T> or Comparator<? super super Integer>.

Why in my example it becomes Comparator<Object>?

Is this a compiler flaw or is it guarding me from something?

Upvotes: 2

Views: 102

Answers (1)

MC Emperor
MC Emperor

Reputation: 23017

You're defining a as a Comparator<? super Integer>, and your assignment (x, y) -> Integer.compare(x, y) fulfills it.

However, the compiler does not know what exact type ? is. It could be an Object, a Number or an Integer itself, but which one is not known. thenComparing() relies on the type argument of a, for its signature is Comparator<T> thenComparing(Comparator<? super T>). You are passing in a Comparator<Integer>, but a's type argument does not match.

Generics are invariant. A Comparator<? super Integer> is not a Comparator<Integer>. Use the wildcard only if you don't care about the type. Otherwise, use the proper type argument.

Define a as a Comparator<Integer> in order to fix it.


Here's an excellent answer to another Stackoverflow post, explaining why generics are not implicitly polymorphic. It also explains what would be the problem if generics were.

Upvotes: 4

Related Questions