问题
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