usan usa una tipos tamaño superior sistema salida representar representa qué que punto por para opciones opcion nivel los listar letra empiecen doble directorio comodines como comando carácter caracteres argumentos archivos archivo acomodará java optional java-9 supplier

java - usa - ¿Por qué son los comodines de parámetros de tipo de proveedor de métodos opcionales o flatMap?



tipos de comodines (3)

El método Optional.or se agregó en Java 9. Esta es la firma del método

public Optional<T> or​(Supplier<? extends Optional<? extends T>> supplier)

¿Por qué está tomando el parámetro de tipo del Supplier ? extends Optional ? extends Optional lugar de Optional , ya que Optional es una clase final ?

Lo mismo es cierto para el método Optional.flatMap . Este es un cambio de Java 8.

En Java 8, era la Function<? super T, Optional<U>> mapper Function<? super T, Optional<U>> mapper mientras que se cambió a la Function<? super T,​? extends Optional<? extends U>> Function<? super T,​? extends Optional<? extends U>> Function<? super T,​? extends Optional<? extends U>> en Java 9.


Encontré el razonamiento detrás de esto del propio Stuart Marks.

http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-October/044026.html

Esto tiene que ver con los genéricos anidados ( Optional está anidado dentro de la Function ). Desde el hilo del correo

Function<..., Optional<StringBuilder>>

no es un subtipo de

Function<..., Optional<? extends CharSequence>>

Para solucionar esto, también tenemos que agregar el comodín externo, para que

Function<..., Optional<StringBuilder>>

es un subtipo de

Function<..., ? extends Optional<? extends CharSequence>>


FWIW, un issue similar con los argumentos covariantes todavía existe en Stream.iterate y Stream.iterate en Java 11. Las firmas de métodos actuales son

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

Estas firmas no permiten algunas combinaciones de semillas y UnaryOperator que se UnaryOperator desde una perspectiva de tipo, por ejemplo, lo siguiente no se compila:

UnaryOperator<String> op = s -> s; Stream<CharSequence> scs = iterate("", op); // error

La solución propuesta es cambiar las firmas del método a

static <T, S extends T> Stream<T> iterate(S seed, Predicate<? super S> hasNext, UnaryOperator<S> next) static <T, S extends T> Stream<T> iterate(S seed, UnaryOperator<S> f)

Por lo tanto, en contraste con Optional.or y Optional.flatMap este es un caso donde el "enfoque de parámetros de tipo adicional" realmente funciona.


Sí ... se dice que el comodín con un límite de extensión (límite superior) hace que el tipo sea covariante , lo que significa que, por ejemplo, la List<Apple> es un subtipo real de la List<? extends Fruit> List<? extends Fruit> (considerando que Apple extiende Fruit ); Esto también se llama covarianza .

O en los ejemplos que ha mostrado, significa que Optional<StringBuilder> es un subtipo de Optional<? extends Optional<? extends CharSequence>> Optional<? extends Optional<? extends CharSequence>> Optional<? extends Optional<? extends CharSequence>> , por lo que podría, por ejemplo, hacer:

List<Optional<String>> left = new ArrayList<>(); List<? extends Optional<? extends CharSequence>> right = new ArrayList<>(); right = left; // will compile

o asignar una Function a la otra