2

我有一个返回Stream类型的方法AB我也有一个A. 该方法创建一个Stream它填充的实例,由于继承B,这些实例也是类型。A这很好用,直到我在Stream. 然后,编译器决定 Stream 是 typeB而不是A,继承似乎无关紧要。为什么会这样?

这是一个最小的可重现示例:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Main {

    abstract class A {
        int member;
    }

    class B extends A {

        public B(int member) {
            this.member = member;
        }
    }

    public static void main(String[] args) {
        Stream<A> stream = getStream();
    }

    private Stream<A> getStream() {
        List<Integer> ints = new ArrayList<>();
        ints.add(1);
        ints.add(2);
        ints.add(3);

        return ints.stream().map(B::new).filter(b -> true); // Filter causes compiler to throw error
    }

}
4

2 回答 2

4

感谢 Holger,为您直截了当。这是泛型类型的类型推断没有扩展到链式调用的情况,因为它会带来额外的复杂性。因此,一旦您链接filter()调用,推理机制就无法再自动确定类型。

除了在调用中指定泛型类型之外,您不需要使用额外的 clumsy 进行强制转换.map(A.class::cast)修改返回类型Stream<? extends A>或执行任何其他操作map()

return ints.stream().<A>map(B::new).filter(b -> true);
于 2020-06-05T17:58:29.747 回答
0

(对评论做出反应,但太长了)

filter()方法不强制转换Stream<A>Stream<B>,实际上map()返回可以分配给两者的东西Stream<A>Stream<B>(自己尝试 - 将映射重构为局部变量)。推理机制很复杂,并且还考虑了目标类型(即重构的局部变量或 - 如在您的原始示例中 - 方法返回类型,在这种情况下,流程被filter方法破坏)。

您可以将返回类型更改Stream<? extends A>为 Alex 所写的,或在 originalmapfilter:之间添加显式向上转换.map(A.class::cast)。坦率地说,我现在看不到任何提议的意义。

于 2020-06-05T17:56:37.463 回答