I have set Netbeans to show unchecked warnings in my Java code, but I am failing to understand the error on the following lines:
private List<String> cocNumbers;
private List<String> vatNumbers;
private List<String> ibans;
private List<String> banks;
...
List<List<String>> combinations = Utils.createCombinations(cocNumbers, vatNumbers, ibans);
Gives:
[unchecked] unchecked generic array creation for varargs parameter of type List<String>[]
Method source:
/**
* Returns a list of all possible combinations of the entered array of lists.
*
* Example: [["A", "B"], ["0", "1", "2"]]
* Returns: [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]
*
* @param <T> The type parameter
* @param elements An array of lists
* @return All possible combinations of the entered lists
*/
public static <T> List<List<T>> createCombinations(List<T>... elements) {
List<List<T>> returnLists = new ArrayList<>();
int[] indices = new int[elements.length];
for (int i = 0; i < indices.length; i++) {
indices[i] = 0;
}
returnLists.add(generateCombination(indices, elements));
while (returnLists.size() < countCombinations(elements)) {
gotoNextIndex(indices, elements);
returnLists.add(generateCombination(indices, elements));
}
return returnLists;
}
What is exactly going wrong and how would I fix it, as I suppose leaving unchecked warnings in the code is not a good idea?
Forgot to mention, but I am using Java 7.
Edit: Also I see now that the method has the following:
[unchecked] Possible heap pollution from parameterized vararg type List<T>
where T is a type-variable:
T extends Object declared in method <T>createCombinations(List<T>...)
As janoh.janoh mentioned above, varargs in Java is just a syntactic sugar for arrays plus the implicit creation of an array at the calling site. So
List<List<String>> combinations =
Utils.createCombinations(cocNumbers, vatNumbers, ibans);
is actually
List<List<String>> combinations =
Utils.createCombinations(new List<String>[]{cocNumbers, vatNumbers, ibans});
But as you may know, new List<String>[]
is not allowed in Java, for reasons that have been covered in many other questions, but mainly have to do with the fact that arrays know their component type at runtime, and check at runtime whether elements added match its component type, but this check is not possible for parameterized types.
Anyway, rather than failing, the compiler still creates the array. It does something similar to this:
List<List<String>> combinations =
Utils.createCombinations((List<String>[])new List<?>[]{cocNumbers, vatNumbers, ibans});
This is potentially unsafe, but not necessarily unsafe. Most varargs methods simply iterate over the varargs elements and read them. In this case, it doesn't care about the runtime type of the array. This is the case with your method. Since you are on Java 7, you should add the @SafeVarargs
annotation to your method, and you won't get this warning anymore. This annotation basically says, this method only cares about the types of the elements, not the type of the array.
However, there are some varargs methods that do use the runtime type of the array. In this case, it is potentially unsafe. That's why the warning is there.
Because java compiler uses an implicit array creation for varargs, and java doesn't allow a generic array creation (because type argument is not reifiable).
The code below is correct (these operations are allowed with arrays), so unchecked warning is needed:
public static <T> List<List<T>> createCombinations(List<T> ... lists) {
((Object[]) lists)[0] = new ArrayList<Integer>();
// place your code here
}
See a comprehensive explanation here
How is about suppressing of warning?
@SuppressWarnings("unchecked")