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?
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
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
Ts 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
Lower-bounded wildcards are as loose as you can get while also being typesafe. With just plain
Supplier<T> parameters, you wouldn’t be able to directly pass a
Consumer<Object> to a
forEach method without casting. With unbounded wildcards, you would be able to pass basically anything, which defeats the whole point of using generics.