Stream.findFirst与Optional.of不同? [英] Stream.findFirst different than Optional.of?
问题描述
假设我有两个课程和两个方法:
Lets say I have two classes and two methods:
class Scratch {
private class A{}
private class B extends A{}
public Optional<A> getItems(List<String> items){
return items.stream()
.map(s -> new B())
.findFirst();
}
public Optional<A> getItems2(List<String> items){
return Optional.of(
items.stream()
.map(s -> new B())
.findFirst()
.get()
);
}
}
为什么 getItems2
编译而 getItems
给出编译器错误
Why does getItems2
compile while getItems
gives compiler error
incompatible types: java.util.Optional<Scratch.B> cannot be converted to java.util.Optional<Scratch.A>
所以,当我获取
的价值时可选
由 findFirst
返回并再次用 Optional.of
如果直接使用 findFirst
的结果,编译器会识别继承但不会。
So when I get
the value of the Optional
returned by findFirst
and wrap it again with Optional.of
the compiler recognizes the inheritance but not if I use directly the result of findFirst
.
推荐答案
可选< B>
不是的子类型< A>
。与其他编程语言不同,Java的泛型类型系统不知道只读类型或输出类型参数,因此它不理解可选< B>
仅提供 B
的实例,可以在需要 Optional< A>
的地方使用。
An Optional<B>
is not a subtype of Optional<A>
. Unlike other programming languages, Java’s generic type system does not know "read only types" or "output type parameters", so it doesn’t understand that Optional<B>
only provides an instance of B
and could work at places where an Optional<A>
is required.
当我们写一个类似
Optional<A> o = Optional.of(new B());
Java的类型推断使用目标类型来确定我们想要
Java’s type inference uses the target type to determine that we want
Optional<A> o = Optional.<A>of(new B());
有效新B()
可以在需要 A
的实例的情况下使用。
which is valid as new B()
can be used where an instance of A
is required.
这同样适用于
return Optional.of(
items.stream()
.map(s -> new B())
.findFirst()
.get()
);
其中方法声明的返回类型用于推断的类型参数Optional.of
调用并传递 get()
的结果, B的实例
,其中 A
是必需的。
where the method’s declared return type is used to infer the type arguments to the Optional.of
invocation and passing the result of get()
, an instance of B
, where A
is required, is valid.
不幸的是,这种目标类型推断无法通过链式调用工作,所以对于
Unfortunately, this target type inference doesn’t work through chained invocations, so for
return items.stream()
.map(s -> new B())
.findFirst();
它不用于地图
来电。因此,对于 map
调用,类型推断使用 new B()
的类型,其结果类型将为流< B个
。第二个问题是 findFirst()
不是通用的,在上调用它< T>
总是产生一个可选< T>
(并且Java的泛型不允许声明类型变量,如< R super T>
,所以甚至不可能在此处生成可选< R>
并带有所需的类型。)
it is not used for the map
call. So for the map
call, the type inference uses the type of new B()
and its result type will be Stream<B>
. The second problem is that findFirst()
is not generic, calling it on a Stream<T>
invariably produces a Optional<T>
(and Java’s generics does not allow to declare a type variable like <R super T>
, so it is not even possible to produce an Optional<R>
with the desired type here).
→解决方案是为地图提供显式类型
调用:
public Optional<A> getItems(List<String> items){
return items.stream()
.<A>map(s -> new B())
.findFirst();
}
为了完整性,如上所述, findFirst()
不是通用的,因此不能使用目标类型。链接允许类型更改的通用方法也可以解决问题:
Just for completeness, as said, findFirst()
is not generic and hence, can’t use the target type. Chaining a generic method allowing a type change would also fix the problem:
public Optional<A> getItems(List<String> items){
return items.stream()
.map(s -> new B())
.findFirst()
.map(Function.identity());
}
但我建议使用为<$ c提供显式类型的解决方案$ c> map 调用。
这篇关于Stream.findFirst与Optional.of不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!