1

My question is based off the answer to a previous question:

Why we can't do List<Parent> mylist = ArrayList<child>();

I have a function that sorts a list of children that is passed to it based on the parameters in the parent function. Since there are many different types of children I wrote a function that receives a generic parent type.

void sort(ArrayList<? extends Parent> passedList)

Later in the function, I would like to swap two members (i and j) of the ArrayList, but I cannot figure out how. I have tried:

Parent swap;
swap = passedList.get(i);
passedList.set(i,passedList.get(j));
passedList.set(j,swap);

However this will not compile and it says the types are not compatible in the set function. The type that I receive from get is Parent, but set expects a type of (? extends Parent). I have also tried declaring swap as ? extends Parent swap; or by casting as in

passedList.set(i,(? extends Parent)passedList.get(j));

It seems like it should be possible seeing as how we can guarantee that the object returned by passedList.get() is the right type to belong in the arraylist.

Community
  • 1
  • 1
Tony Ruth
  • 1,358
  • 8
  • 19

2 Answers2

1

<? extends Parent> promises that the list is a list containing Parents, or a list containing a subclass of Parent, such as ArrayList<Child>.

This means that you can always get an object out as a Parent, but you can't put a Parent back in there, since the actual list type may not be Parent (and you can't put a Parent in a List<Child>).

Kayaman
  • 72,141
  • 5
  • 83
  • 121
1

It seems like it should be possible seeing as how we can guarantee that the object returned by passedList.get() is the right type to belong in the arraylist.

We can tell that it is correct, because we can look at the code and trace back to where swap comes from. But the compiler cannot tell, because it is not guaranteed by the language. You are trying to put a Parent in a List<? extends Parent>, and the list may be some subtype, like List<Child>.

Instead, you can accomplish this with wildcard capture:

static <P extends Parent> void swap(List<P> list, int i, int j) {
    P temp = list.get(i);
    list.set(i, list.get(j));
    list.set(j, temp);
}

This lets you express that the type of temp is the same as the actual type argument to list.

See also:

Radiodef
  • 37,180
  • 14
  • 90
  • 125