2

For Java 8 source code in Stream class:

public static<T> Stream<T> generate(Supplier<T> s) {
        ...
}

In Optional class

public T orElseGet(Supplier<? extends T> other) {
    ...
}

I already read this post: PECS, but I have some confusison.

Why generate method parameter(Supplier<T> s) use non-variance, but orElseGet method parameter(Supplier<? extends T> other) use Covariance, how to decide use Covariance or non-variance?

Guo
  • 1,761
  • 2
  • 22
  • 45

1 Answers1

1

Looks like the Java developers agreed with you that generate should accept Supplier<? extends T>, as it was changed in Java 9. See JDK-8132097 (Stream.generate should use a covariant Supplier as parameter):

Description

The signature of Stream.generate doesn't to use a wildcard (? extends) hence some programs are rejected even if they are valid. The signature should be public static Stream generate(Supplier<? extends T> s).

The change makes sense, as doing something like the this:

Stream<CharSequence> stream = Stream.generate(new Supplier<String>() {
    @Override public String get() {
      // implementation...
    }
});

Should be perfectly valid. Admittedly, that is a very contrived example, but the point stands: The Supplier should be allowed to be parameterized with any subtype of T. And to relate this to PECS, the Supplier is functioning as a producer of T.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • but why **Stream.collect** ` R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner);` not use **Covariance**? – Guo Dec 03 '21 at 03:50
  • I can't give a positive answer, because I wasn't involved in the development process for streams. However, my guess is that it was either an oversight or that they thought it was unnecessary; given typical usage of streams, it's likely rare that the fact covariance is not used would actually cause a problem. But there also might be some obscure problem with type resolution if they used `? extends R` everywhere, not sure (or maybe there _was_ a problem in Java 8, but it may no longer be a problem now as type inference has been improved over time). – Slaw Dec 03 '21 at 03:56
  • To speculate why it wasn't changed along with `generate`, it may simply be that no one has submitted a bug report for `collect`. Though the fact `generate` is a static method, and thus cannot be overridden, may make it easier to change without breaking backwards compatibility. – Slaw Dec 03 '21 at 03:59
  • Thanks! It's very helpful to me. `Stream.collect()` is still keep **non-variance** in **Java17**. I don't know why. – Guo Dec 03 '21 at 06:34