Skip to content
Advertisement

Using wildcards in stream terminal operations

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 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 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.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement