为什么Optional或flatMap方法的供应商类型参数是通配符?

use*_*er7 29 java optional java-9 supplier

Optional.or方法是在Java 9中添加的.这是方法签名

public Optional<T> or?(Supplier<? extends Optional<? extends T>> supplier)
Run Code Online (Sandbox Code Playgroud)

为什么是的类型参数Supplier回吐? extends Optional,而不是仅仅Optional因为Optional最后的类?

Optional.flatMap方法也是如此.这是Java 8的变化.

在Java 8中,它被Function<? super T, Optional<U>> mapper改为Function<? super T,?? extends Optional<? extends U>>Java 9.

use*_*er7 35

我从斯图尔特马克斯自己身上找到了这个原因

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

这与嵌套泛型(Optional嵌套在其中Function)有关.来自邮件线程

 Function<..., Optional<StringBuilder>>
Run Code Online (Sandbox Code Playgroud)

不是的子类型

 Function<..., Optional<? extends CharSequence>>
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我们还必须添加外部通配符,以便这样做

 Function<..., Optional<StringBuilder>>
Run Code Online (Sandbox Code Playgroud)

是一个子类型

 Function<..., ? extends Optional<? extends CharSequence>>
Run Code Online (Sandbox Code Playgroud)

  • +1.对我来说,真正令人难以置信的是为什么更简单的"附加类型参数方法"`<V,U扩展V>可选<V> flatMap(函数<?super T,可选<U >>映射器)会*不会*在所有情况下工作. (8认同)

Ste*_*bel 10

FWIW,与协变性参数类似的问题仍存在于Java 11 中的Stream.iterateStream.iterate中.当前的方法签名是

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
Run Code Online (Sandbox Code Playgroud)

这些签名不允许UnaryOperator从类型角度看声音的种子和s的某些组合,例如以下不编译:

UnaryOperator<String> op = s -> s; 
Stream<CharSequence> scs = iterate("", op); // error
Run Code Online (Sandbox Code Playgroud)

建议的解决方案是将方法签名更改为

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)
Run Code Online (Sandbox Code Playgroud)

因此,与Optional.orOptional.flatMap相比, 这是"附加类型参数方法"实际工作的情况.


Eug*_*ene 9

是的...据说带有扩展边界(上限)的通配符使得类型协变,这意味着例如List<Apple>List<? extends Fruit>(考虑到Apple扩展Fruit)的实际子类型; 这也称为协方差.

或者在您显示的示例中,这意味着它Optional<StringBuilder>是一个子类型Optional<? extends Optional<? extends CharSequence>>,因此您可以执行以下操作:

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

right = left; // will compile
Run Code Online (Sandbox Code Playgroud)

或指定Function给另一个