Trouble with wildcards
Zhong Yu
zhong.j.yu at gmail.com
Tue Dec 17 12:35:07 PST 2013
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
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