Trouble with wildcards

Remi Forax forax at univ-mlv.fr
Tue Dec 17 11:46:41 PST 2013


On 12/17/2013 07:21 PM, Dan Smith wrote:
> On Dec 16, 2013, at 7:42 AM, Paul Sandoz <paul.sandoz at oracle.com> 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...
> The concrete explanation: the 'and' method of the type Predicate<[something]>, where [something] is some type that is a supertype of Y (written CAP#1 in the error message), requires a Predicate<? super [something]>.  Is a Predicate<Y> a Predicate<? super [something]>?  No.  For example, consider the case in which [something] is Object.

I disagree, Predicate<Y> is a Predicate<? super [something]> because Y 
can capture
? super [something], otherwise it means that 'and' should be a static 
method and not an instance method.

The following code compiles:
static <T> Predicate<T> staticAnd(Predicate<? super T> that, Predicate<? 
super T> other) {
     ...
}

Predicate<? super String> p1 = null;
Predicate<? super String> p2 = null;
Predicate<? super String> p3 = staticAnd(p1,p2);

but not
   Predicate<? super String> p3 = p1.and(p2);
which is not very logical.

>
> The abstract explanation: we accept that 'px.and(py)' is a type error, right?  So it certainly doesn't make any sense that _up-casting_ px to one of its supertypes (Predicate<? super Y> in this case) would provide some functionality that px itself doesn't have.
>
> —Dan

Rémi



More information about the lambda-dev mailing list