Stream.findFirst 与 Optional.of 不同?

假设我有两个类和两个方法:


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


梦里花落0921
浏览 169回答 3
3回答

catspeake

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(&nbsp; &nbsp; &nbsp; &nbsp; items.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.map(s -> new B())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.findFirst()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.get()&nbsp; &nbsp; );其中方法声明的返回类型用于推断Optional.of调用的类型参数并传递 的结果,其中需要get()的实例是有效的。BA不幸的是,这种目标类型推断不适用于链式调用,因此对于return items.stream()&nbsp; &nbsp; &nbsp;.map(s -> new B())&nbsp; &nbsp; &nbsp;.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){&nbsp; &nbsp; return items.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.<A>map(s -> new B())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.findFirst();}如前所述,仅出于完整性考虑,findFirst()它不是通用的,因此不能使用目标类型。链接允许类型更改的通用方法也可以解决问题:public Optional<A> getItems(List<String> items){&nbsp; &nbsp; return items.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.map(s -> new B())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.findFirst()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.map(Function.identity());}但我建议使用为map调用提供显式类型的解决方案。

ITMISS

您遇到的问题是泛型的继承。Optional< B > 不扩展 Optional< A >,因此不能这样返回。我会想象这样的事情:public Optional<? extends A> getItems( List<String> items){&nbsp; &nbsp; return items.stream()&nbsp; &nbsp; &nbsp; &nbsp; .map(s -> new B())&nbsp; &nbsp; &nbsp; &nbsp; .findFirst();}或者:public Optional<?> getItems( List<String> items){&nbsp; &nbsp; return items.stream()&nbsp; &nbsp; &nbsp; &nbsp; .map(s -> new B())&nbsp; &nbsp; &nbsp; &nbsp; .findFirst();}可以正常工作,取决于您的需要。编辑:转义一些字符

桃花长相依

AnOptional<B>不是的子类Optional<A>。在第一种情况下,您有一个Stream<B>,因此findFirst返回一个Optional<B>,它不能转换为一个Optional<A>。在第二种情况下,您有一个流管道,它返回一个B.&nbsp;当您将该实例传递给Optional.of()时,编译器会看到该方法的返回类型是Optional<A>,因此Optional.of()返回一个Optional<A>(因为 anOptional<A>可以将 的实例B作为其值(因为Bextends&nbsp;A))。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java