Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Collections.swap assign the target list to a variable of a raw type?

Tags:

java

In the source for JDK 1.6, the Collections class' swap method is written like this:

public static void swap(List<?> list, int i, int j) {
    final List l = list;
    l.set(i, l.set(j, l.get(i)));
}

What reason is there for creating a final copy of the passed list? Why don't they simply modify the passed list directly? In this case, you also get the raw type warning.

like image 872
Sotirios Delimanolis Avatar asked May 28 '12 17:05

Sotirios Delimanolis


People also ask

What does Collection swap do?

The swap() method of java. util. Collections class is used to swap the elements at the specified positions in the specified list. If the specified positions are equal, invoking this method leaves the list unchanged.


1 Answers

There is no copy of the list, there is only a copy of the reference to the list. The final keyword is not important. However, it is important that a raw type is used. If the parameter would be used instead, the compiler would report an error:

public static void swap(List<?> list, int i, int j) {
    // ERROR: The method set(int, capture#3-of ?) in the type List<capture#3-of ?>
    // is not applicable for the arguments (int, capture#4-of ?)
    list.set(i, list.set(j, list.get(i)));
}

This means, that they are using the intermediate variable to circumvent the shortcomings of generics, and to get rid of the error message.

The interesting question is: Why don't they use a generic method? The following code works:

public static <T> void swap(List<T> list, int i, int j) {
    list.set(i, list.set(j, list.get(i)));
}

The answer is, that this method produces warnings in old code invoking the method with raw types:

List list = ...;
// WARNING: Type safety: Unchecked invocation swap2(List, int, int)
// of the generic method swap2(List<T>, int, int) of type Swap
Collections.swap(list, 0, 1);
like image 126
nosid Avatar answered Sep 28 '22 00:09

nosid