Sotirios Delimanolis Sotirios Delimanolis - 3 months ago 26
Java Question

Why does Collections.swap copy the input list?

In the source for JDK1.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.

Answer

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);