Why is it ? extends U
and not U
?
Because of code conventions. Check out @deduper's answer for a great explanation.
Is there any actual difference?
When writing your code normally, your compiler will infer the correct T
for things like Supplier<T>
and Function<?, T>
, so there is no practical reason to write Supplier<? extends T>
or Function<?, ? extends T>
when developing an API.
But what happens if we specify the type manually?
void test() {
Supplier<Integer> supplier = () -> 0;
this.strict(supplier); // OK (1)
this.fluent(supplier); // OK
this.<Number>strict(supplier); // compile error (2)
this.<Number>fluent(supplier); // OK (3)
}
<T> void strict(Supplier<T>) {}
<T> void fluent(Supplier<? extends T>) {}
As you can see, strict()
works okay without explicit declaration because T
is being inferred as Integer
to match local variable's generic type.
Then it breaks when we try to pass Supplier<Integer>
as Supplier<Number>
because Integer
and Number
are not compatible.
And then it works with fluent()
because ? extends Number
and Integer
are compatible.
In practice that can happen only if you have multiple generic types, need to explicitly specify one of them and get the other one incorrectly (Supplier
one), for example:
void test() {
Supplier<Integer> supplier = () -> 0;
// If one wants to specify T, then they are forced to specify U as well:
System.out.println(this.<List<?>, Number> supplier);
// And if U happens to be incorrent, then the code won't compile.
}
<T, U> T method(Supplier<U> supplier);
Example with Comparator
(original answer)
Consider the following Comparator.comparing
method signature:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, U> keyExtractor
)
Also here is some test classes hierarchy:
class A implements Comparable<A> {
public int compareTo(A object) { return 0; }
}
class B extends A { }
Now let's try this:
Function<Object, B> keyExtractor = null;
Comparator.<Object, A>comparing(keyExtractor); // compile error
error: incompatible types: Function<Object,B> cannot be converted to Function<? super Object,A>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…