Hi2all.
I’am reading a Java book and got to the chapter about StreamAPI classes. So, my questions is: why in terminal operation methods using lower bounded wildcards, like:
void forEach(Consumer<? super T> consumer) boolean anyMatch(Predicate <? super T> pred) Optional<T> min(<? super T> comparator)
Indeed, in fact, you can use unbounded wildcards like this:
void forEach(Consumer<?> consumer) boolean anyMatch(Predicate <?> pred) Optional<T> min(<?> comparator)
Is there any reason to use exactly lower- bounded wildcards?
Advertisement
Answer
You cannot use unbounded wildcards for these methods.
Suppose you are implementing your own forEach
method. If it accepts a Consumer<? super T>
, you can pass a T
to it, because you know that T
is a subtype of whatever the Consumer
‘s parameter’s type is and can therefore safely make the consumer accept an element of type T
.
However, if it accepts a Consumer<?>
, you can’t directly pass a T
to it without casting. There is no guarantee that the consumer accepts T
s and not some other type? Furthermore, as Louis Wasserman pointed out in his answer, you would be able to pass a Consumer<Long>
to the forEach
method of a Stream<String>
.
Lower-bounded wildcards are as loose as you can get while also being typesafe. With just plain Consumer<T>
and Supplier<T>
parameters, you wouldn’t be able to directly pass a Consumer<Object>
to a Stream<String>
‘s forEach
method without casting. With unbounded wildcards, you would be able to pass basically anything, which defeats the whole point of using generics.