Trouble with wildcards
Remi Forax
forax at univ-mlv.fr
Tue Dec 17 14:50:32 PST 2013
On 12/17/2013 09:35 PM, Zhong Yu wrote:
> The static method works because it has an extra type parameter, which
> gives javac the freedom to make things work. The instance and() method
> has no such freedom (unless we give it a type parameter <S extends T>)
>
> Zhong Yu
The instance method and() is called on a Predicate<? super T>, and Predicate
is declared as class Predicate<T>, here T is already your extra type
variable.
Rémi
>
> On Tue, Dec 17, 2013 at 1:46 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> 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