Java – Using Type Parameters Effectively

genericsjava

Effective Java provides 2 ways to implement swap:

// Two possible declarations for the swap method 
public static <E> void swap(List<E> list, int i, int j); 
public static void swap(List<?> list, int i, int j);

Then, Mr. Bloch says:

Which of these two declarations is preferable, and why? In a public
API, the second is better because it's simpler. You pass in a list—any
list—and the method swaps the indexed elements. There is no type
parameter to worry about. As a rule, if a type parameter appears only
once in a method declaration, replace it with a wildcard.

It appears that swapNoWildCard could be used rather than the swap and swapHelper method. Mr. Bloch explains the reasoning for using the 2nd signature above.

public static <E> void swapNoWildcard(List<E> list, int i, int j) {
    E e = list.set(j, list.get(i));
    list.set(i, e);
}

public static void swap(List<?> list, int i, int j) {
    swapHelper(list, i, j);
}

private static <E> void swapHelper(List<E> list, int i, int j) {
    E e = list.set(j, list.get(i));
    list.set(i, e);
}

However, is this debatable given the fact that swapNoWildCard is almost half the # of lines of code compared to implementing the other 2 methods?

Why is it so useful to leave out the type parameter?

Best Answer

In good software design what you want, or better yet in an idealized world you must, have an interface which communicates intent. Taking away the type parameter of the List expressed that intent clearly. You're telling the caller "I'm only interested in acting on a List and nothing more." This is why the second is better than the first.

As an aside, the reason that the second method requires two function calls is that Java does not have type inference so you are forced to declare an E to capture one of the swapped values.