Trouble with wildcards

Zhong Yu zhong.j.yu at gmail.com
Mon Dec 16 15:10:45 PST 2013


Not exactly sure what you guys are talking about... but I guess it's a
complaint about the signature of Predicate.and()?

It might be changed to be more receptive, like

    <S extends T> Predicate<S> and(Predicate<? super S> other)

then the previous examples could be compiled, as well as this one

    Predicate<Serializable> p1 = null;
    Predicate<CharSequence> p2 = null;
    Predicate<String> p3 = p1.and(p2);

Zhong Yu



On Mon, Dec 16, 2013 at 3:38 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> On 12/16/2013 03:42 PM, Paul Sandoz wrote:
>> 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.
>
> indeed :)
>
> Rémi
>
>>
>> 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