Trouble with wildcards
Paul Sandoz
paul.sandoz at oracle.com
Mon Dec 16 06:42:43 PST 2013
Hi Remi,
Reducing it down a little:
import java.util.*;
import java.util.function.*;
class A {
static class X {};
static class Y extends X {};
public static void main(String[] args) {
Predicate<X> px = x -> x instanceof X;
Predicate<Y> py = y -> y instanceof Y;
Predicate<? super Y> psy = px;
Predicate<? super Y> superyandy = psy.and(py); // <-- error
superyandy.test(new Y());
}
}
$ javac -Xdiags:verbose A.java
A.java:15: error: method and in interface Predicate<T> cannot be applied to given types;
Predicate<? super Y> superyandy = psy.and(py); // <-- error
^
required: Predicate<? super CAP#1>
found: Predicate<Y>
reason: argument mismatch; Predicate<Y> cannot be converted to Predicate<? super CAP#1>
where T is a type-variable:
T extends Object declared in interface Predicate
where CAP#1 is a fresh type-variable:
CAP#1 extends Object super: Y from capture of ? super Y
1 error
It's confusing...
Paul.
On Dec 14, 2013, at 7:43 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> Hi all,
> I've tried to explain in code how a Stream (here a Flow to avoid
> confusion) can be implemented (just filter/map, only a sequential
> stream) with consecutive operations, filter.filter or map.map optimized.
>
> I end up with the code below which compiles but if instead of
> return Flow.this.filter(/*predicate.and(predicate2)*/ t ->
> predicate.test(t) && predicate2.test(t));
> I replace it by
> return Flow.this.filter(predicate.and(predicate2));
> the compiler refuses to compile and I don't understand why :(
>
> Here predicate is a Predicate<? super T>, so predicate2 should be a
> Predicate<? super ? super T>,
> because and() is declared like this: Predicate<T>.and(Predicate<? super T>)
> predicate2 is a Predicate<? super T> so it should match Predicate<?
> super ? super T> but
> it doesn't.
>
> Is it a bug in the compiler or in my head ?
>
> cheers,
> Rémi
>
> @FunctionalInterface
> public interface Flow<T> {
> public void forEach(Consumer<? super T> consumer);
>
> public default Flow<T> filter(Predicate<? super T> predicate) {
> return new Flow<T>() {
> @Override
> public void forEach(Consumer<? super T> consumer) {
> Flow.this.forEach(u -> {
> if (predicate.test(u)) {
> consumer.accept(u);
> }
> });
> }
> @Override
> public Flow<T> filter(Predicate<? super T> predicate2) {
> return Flow.this.filter(/*predicate.and(predicate2)*/ t ->
> predicate.test(t) && predicate2.test(t));
> }
> };
> }
>
> public default <R> Flow<R> map(Function<? super T, ? extends R>
> function) {
> return new Flow<R>() {
> @Override
> public void forEach(Consumer<? super R> consumer) {
> Flow.this.forEach(t -> consumer.accept(function.apply(t)));
> }
> @Override
> public <U> Flow<U> map(Function<? super R, ? extends U> function2) {
> return Flow.this.map(function.andThen(function2));
> }
> };
> }
>
> public static <T> Flow<T> create(Iterable<? extends T> iterable) {
> return iterable::forEach;
> }
>
> public static void main(String[] args) {
> List<Integer> list = IntStream.range(0,
> 10).boxed().collect(Collectors.toList());
> Flow<Integer> flow = create(list);
> flow.filter(x -> x != 5).filter(x -> x !=
> 2).forEach(System.out::println);
> flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println);
> flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x
> -> x / 2).forEach(System.out::println);
> }
> }
>
More information about the lambda-dev
mailing list