What is an apparently correct example of Java code causing heap pollution?

user118967 :

I'm trying to decide what to do every time I get a Java heap pollution warning when using parameterized varargs such as in

public static <T> LinkedList<T> list(T... elements) {
    ...
}

It seems to me that if I am confident not to be using some weird casts in my methods, I should just use @SafeVarargs and move on. But is this correct, or do I need to be more careful? Is there apparently correct code that is actually not safe when using parameterized varargs?

Reading about the subject, I notice that the provided examples are quite artificial. For example, the Java documentation shows the following faulty method:

public static void faultyMethod(List<String>... l) {
    Object[] objectArray = l;     // Valid
    objectArray[0] = Arrays.asList(42);
    String s = l[0].get(0);       // ClassCastException thrown here
}

which is didactic but pretty unrealistic; experienced programmers are not likely to write code doing stuff like this. Another example is

Pair<String, String>[] method(Pair<String, String>... lists) { 
   Object[] objs = lists; 
   objs[0] = new Pair<String, String>("x", "y");  
   objs[1] = new Pair<Long, Long>(0L, 0L);  // corruption !!! 
   return lists; 
} 

which is again pretty obviously mixing types in an unrealistic way.

So, are there more subtle cases in which heap pollution happens under parameterized varargs? Am I justified in using @SafeVarargs if I am not casting variables in a way that loses typing information, or mixes types incorrectly? In other words, am I justified in treating this warning as a not very important formality?

user118967 :

To declare generic arrays T[] in Java is problematic because their type is not known at run time and as a consequence they can be misused, as the examples in the question show. So the Java compiler issues warnings whenever this is done.

For example, if we declare a generic array as in

T[] tArray = (T[]) new Object[] { 42 };

we get an "unchecked cast" warning.

Besides such casts, the only other way of introducing a generic array into a program is by using a generic varargs. For example, in

void bar() {
    foo(new Integer[]{ 42 })
}

void foo(T... args) {
}

Again here a generic array is being introduced, but in a different way than an unchecked cast, so it gets its own specific warning to make sure the user is not misusing it.

Indeed, as long as one is not converting the array to an array of a different type, it seems that using @SafeVarargs should be safe to use, barring atypical type conversions.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=434891&siteId=1
Recommended