0

This is an extension of this SO answer.

Note: This is not a duplicate of the following. Why List is not a subtype of List<Number> but is subtype of List<? extends Number>?, nor any of the questions this has been marked duplicate of. Let me explain.

The actual question was (edited to remove unnecessary code),

void wildcardsMethod(List<? super Pair<? super Number>> list) {}

//... From some method.
    List<Pair<Object>> list = null;
    wildcardsMethod(list);
    // Error: wildcardsMethod(List<? super Pair<? super Number>>) is not applicable for the arguments (List<Pair<Object>>)

The above doesn't work.

And the answer given was similar to (if I have not misunderstood),

Pair<Object> is a subtype of Pair<? super Number> and so it cannot be used in place of <? super Pair<>>.

I don't understand it in this context. I was thinking it's just a Pair object and we should be able to use it in place of both <? extends Pair<>> and <? super Pair<>>. But it doesn't work in the latter.

Can someone explain why it's considered to be a subtype thus limiting it to only extends and not super.

EDIT:

To explain a little more, let's see why we will the method (considering PECS),

void wildcardsMethod(List<? super Pair<? super Number>> list) {}

You will be using it to add a Pair<Number> object to the passed list.

In this case, List<Pair<Object>> is a valid list which can accept a Pair<Number> object.

So, why is this not allowed?

Community
  • 1
  • 1
Codebender
  • 14,221
  • 7
  • 48
  • 85

3 Answers3

1

You might be missing the forest for the trees, and think that List<Pair<Object>> is the same as List<? super Pair<? super Number>>, when they are not.

List<? super Pair<? super Object>> declares that a list will contain either Pair<Object> or a supertype of Pair<Object>, which could be Object or some other ancestral class between Object and Pair<T>. List<Pair<Object>> declares that only Pair objects or objects that can be considered a Pair will ever exist in that class.

The bounds are going in different directions. You're implicitly getting List<? extends Pair<? super Object>> with the first declaration.

The only way you could reasonably do this is if the list you were passing in were also bound in a similar fashion. That is, you would want to be passing in a List<? super Pair<? super Number>>.

Makoto
  • 104,088
  • 27
  • 192
  • 230
0

When you say "A is a subtype of B", what that means by definition, is that every object of type A is also an object of type B. Now if you declare a variable with Foo<? extends Object> x;, that means that the objects that x can refer to are precisely those objects which are of type Foo<something> (where something extends Object). Obviously, that includes objects of type Foo<String>.

So every Foo<String> is also a Foo<? extends Object> - so by definition, Foo<String> is a subtype of Foo<? extends Object>.

Likewise, every Pair<Object> is also a Pair<? super Number> - so by definition, Pair<Object> is a subtype of Pair<? super Number>.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
0

After thinking about Makoto's answer for sometime I understood what it meant.

Note: I am writing this answer in a format which I can easily understand for future reference (though his will be the accepted answer)

Let's say we have the method in question defined like this (considering PECS),

void wildcardsMethod(List<? super Pair<? super Number>> list) {
    Pair<Number> pairOfNumbers = new Pair<Number>();
    list.add(pairOfNumbers);
}

and we are calling the method with this argument (assuming it was allowed),

List<Pair<Object>> listOfPairOfObjects = new ArrayList<Pair<Object>>();
wildcardsMethod(listOfPairOfObject);

Now, a Pair<Number> object is added to listOfPairOfObjects.

Also remember that the rules of PECS only apply to the list reference in wildcardsMethod and not the listOfPairOfObjects reference.

Hence I can do,

Pair<Object> pairOfObjects = listOfPairOfObjects.get(0);

Now, since a Pair<Number> was added to the list in the method, I will receive a Pair<Number> object when I expect a Pair<Object> reference.

And these both are totally incompatible types. Hence the error.

Codebender
  • 14,221
  • 7
  • 48
  • 85