Reputation: 65
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
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