为什么 Optional 的 or 和 flatMap 方法的供应商类型参数是通配符?
Why are Optional's or and flatMap methods' supplier type parameters wildcards?
在Java9中添加了Optional.or
方法,这是方法签名
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
为什么 Supplier
的类型参数采用 ? extends Optional
而不仅仅是 Optional
,因为 Optional
是 final class?
Optional.flatMap
方法也是如此。这是对 Java 8.
的更改
在 Java 8 中,它是 Function<? super T, Optional<U>> mapper
而在 Java 9 中更改为 Function<? super T,? extends Optional<? extends U>>
。
我从 Stuart Marks 本人那里找到了背后的原因
http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-October/044026.html
这与嵌套泛型有关(Optional
嵌套在 Function
中)。
来自邮件线程
Function<..., Optional<StringBuilder>>
is not a subtype of
Function<..., Optional<? extends CharSequence>>
To get around this, we have to add the outer wildcard as well, so that
Function<..., Optional<StringBuilder>>
is a subtype of
Function<..., ? extends Optional<? extends CharSequence>>
FWIW,Java 11 中的类似 issue with covariant arguments still exists in Stream.iterate and Stream.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)
这些签名不允许种子和 UnaryOperator
s 的某些组合,这些组合从类型的角度来看是合理的,例如以下不编译:
UnaryOperator<String> op = s -> s;
Stream<CharSequence> scs = iterate("", op); // error
建议的解决方案是将方法签名更改为
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)
因此,与 Optional.or and Optional.flatMap 相比,这是 "additional-type-parameter approach" 实际起作用的情况。
是的...据说具有扩展边界(上限)的通配符使类型协变,这意味着例如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
或分配一个Function
给另一个
在Java9中添加了Optional.or
方法,这是方法签名
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
为什么 Supplier
的类型参数采用 ? extends Optional
而不仅仅是 Optional
,因为 Optional
是 final class?
Optional.flatMap
方法也是如此。这是对 Java 8.
在 Java 8 中,它是 Function<? super T, Optional<U>> mapper
而在 Java 9 中更改为 Function<? super T,? extends Optional<? extends U>>
。
我从 Stuart Marks 本人那里找到了背后的原因
http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-October/044026.html
这与嵌套泛型有关(Optional
嵌套在 Function
中)。
来自邮件线程
Function<..., Optional<StringBuilder>>
is not a subtype of
Function<..., Optional<? extends CharSequence>>
To get around this, we have to add the outer wildcard as well, so that
Function<..., Optional<StringBuilder>>
is a subtype of
Function<..., ? extends Optional<? extends CharSequence>>
FWIW,Java 11 中的类似 issue with covariant arguments still exists in Stream.iterate and Stream.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)
这些签名不允许种子和 UnaryOperator
s 的某些组合,这些组合从类型的角度来看是合理的,例如以下不编译:
UnaryOperator<String> op = s -> s;
Stream<CharSequence> scs = iterate("", op); // error
建议的解决方案是将方法签名更改为
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)
因此,与 Optional.or and Optional.flatMap 相比,这是 "additional-type-parameter approach" 实际起作用的情况。
是的...据说具有扩展边界(上限)的通配符使类型协变,这意味着例如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
或分配一个Function
给另一个