printItems("Hello", "World");
printItems(1, 2, 3, 4, 5);
printItems(1.1, 2.2, 3.3);
Watch out for heap pollution
One of the main concerns when using varargs with generics is heap pollution. Heap pollution occurs when the parameterized type of a variable does not agree with the type of the objects it points to. This can happen because varargs arguments are implemented as an array, and arrays in Java don’t have the same type-specificity as generics. For instance, consider this method:
public static <T> void dangerous(List<T>... lists) {
Object[] objects = lists; // Implicit casting to Object array
objects[0] = Arrays.asList(1); // Assigning a List<Integer> to a List<T> array
T first = lists[0].get(0); // ClassCastException thrown here if T is not Integer
}
In this example, you can pass List<String>[]
to the method, but inside the method, it’s possible to insert a List<Integer>
, leading to a ClassCastException
when you try to retrieve an Integer
as if it were a String
.
Addressing heap pollution with @SafeVarargs
Java 7 introduced the @SafeVarargs
annotation to address the heap pollution issue. This annotation asserts that the method does not perform potentially unsafe operations on its varargs parameter. It should be used only when the method is truly safe from heap pollution—that is, it doesn’t store anything in the generic varargs array or do anything to make it accessible to untrusted code.