Cannot return Stream of subclass objects after filtering

橙三吉。 提交于 2020-06-22 13:07:28

问题


I have a method that returns a Stream of type A. I also have a subtype B of A. The method creates a Stream that it populates with instances of B, which are also of type A due to inheritance. This works fine, until I introduce a filter on the Stream. Then, the compiler decides that the Stream is of type B and not A, and inheritance does not seem to matter. Why does this happen?

Here is a minimal reproducible example:

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
    }

}

回答1:


Thank you Holger, for setting the record straight. This is a case of type inference of generics types not having been expanded to chained invocation because of the added complexity it would bring. So as soon as you chain the filter() call, the inference mechanism can't determine the type automatically anymore.

You don't need to cast with an additional clumsy .map(A.class::cast), modify the return type to Stream<? extends A> or do anything else except specify the generic type in the map() call

return ints.stream().<A>map(B::new).filter(b -> true);



回答2:


(reacting on comment but too long)

filter() method does not cast Stream<A> to Stream<B>, actually map() returns something which is assignable into both Stream<A> and Stream<B> (try it yourself - refactor map into local variable). Inference mechanism is complex and takes also the target type into account (i.e. refactored local variable or - as in your original example - the method return type, in this case the flow is broken by filter method).

You can change return type into Stream<? extends A> as Alex wrote, or add explicit upcast between original map and filter: .map(A.class::cast). Frankly, I don't see any sense of either proposal at this moment.



来源:https://stackoverflow.com/questions/62220995/cannot-return-stream-of-subclass-objects-after-filtering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!