Why Stream.generate use non-variance, but Optional.orElseGet use Covariance in Java 8

Viewed 87

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?

1 Answers

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.

Related