为了账号安全,请及时绑定邮箱和手机立即绑定

Stream.findFirst 与 Optional.of 不同?

Stream.findFirst 与 Optional.of 不同?

梦里花落0921 2022-06-30 11:28:01
假设我有两个类和两个方法: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会给出编译器错误incompatible types: java.util.Optional<Scratch.B> cannot be converted to java.util.Optional<Scratch.A>因此,当我返回get的值并用编译器再次包装它时,它会识别继承,但如果我直接使用.OptionalfindFirstOptional.offindFirst
查看完整描述

3 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

AnOptional<B>不是 的子类型Optional<A>。与其他编程语言不同,Java 的泛型类型系统不知道“只读类型”或“输出类型参数”,因此它不理解Optional<B>只提供一个实例B并且可以在需要的地方工作Optional<A>。


当我们写一个像


Optional<A> o = Optional.of(new B());

Java的类型推断使用目标类型来确定我们想要的


Optional<A> o = Optional.<A>of(new B());

这是有效的,new B()可以在需要实例的地方A使用。


这同样适用于


return Optional.of(

        items.stream()

             .map(s -> new B())

             .findFirst()

             .get()

    );

其中方法声明的返回类型用于推断Optional.of调用的类型参数并传递 的结果,其中需要get()的实例是有效的。BA


不幸的是,这种目标类型推断不适用于链式调用,因此对于


return items.stream()

     .map(s -> new B())

     .findFirst();

它不用于map通话。因此对于map调用,类型推断使用的类型,new B()其结果类型将是Stream<B>. 第二个问题是它findFirst()不是泛型的,在 a 上调用它Stream<T>总是会产生 a Optional<T>(并且 Java 的泛型不允许声明像 那样的类型变量<R super T>,因此在这里甚至不可能产生Optional<R>具有所需类型的 a )。


→ 解决方案是为map调用提供显式类型:


public Optional<A> getItems(List<String> items){

    return items.stream()

         .<A>map(s -> new B())

         .findFirst();

}

如前所述,仅出于完整性考虑,findFirst()它不是通用的,因此不能使用目标类型。链接允许类型更改的通用方法也可以解决问题:


public Optional<A> getItems(List<String> items){

    return items.stream()

         .map(s -> new B())

         .findFirst()

         .map(Function.identity());

}

但我建议使用为map调用提供显式类型的解决方案。


查看完整回答
反对 回复 2022-06-30
?
ITMISS

TA贡献1871条经验 获得超8个赞

您遇到的问题是泛型的继承。Optional< B > 不扩展 Optional< A >,因此不能这样返回。


我会想象这样的事情:


public Optional<? extends A> getItems( List<String> items){

    return items.stream()

        .map(s -> new B())

        .findFirst();

}

或者:


public Optional<?> getItems( List<String> items){

    return items.stream()

        .map(s -> new B())

        .findFirst();

}

可以正常工作,取决于您的需要。


编辑:转义一些字符


查看完整回答
反对 回复 2022-06-30
?
桃花长相依

TA贡献1860条经验 获得超8个赞

AnOptional<B>不是子类Optional<A>

在第一种情况下,您有一个Stream<B>,因此findFirst返回一个Optional<B>,它不能转换为一个Optional<A>

在第二种情况下,您有一个流管道,它返回一个B. 当您将该实例传递给Optional.of()时,编译器会看到该方法的返回类型是Optional<A>,因此Optional.of()返回一个Optional<A>(因为 anOptional<A>可以将 的实例B作为其值(因为Bextends A))。


查看完整回答
反对 回复 2022-06-30
  • 3 回答
  • 0 关注
  • 168 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信