未检查的 Java: 未检查的为 varargs 参数创建泛型数组

我已经将 Netbeans 设置为在 Java 代码中显示未检查的警告,但是我无法理解以下代码行中的错误:

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

给予:

[unchecked] unchecked generic array creation for varargs parameter of type List<String>[]

方法来源:

/**
* 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;
}

到底出了什么问题,我该如何修复它,因为我认为在代码中留下未检查的警告不是一个好主意?

忘了说了,我用的是 Java7。

Edit : 现在我还看到该方法具有以下内容:

[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>...)
80219 次浏览

因为 Java 编译器对 varargs 使用隐式数组创建,而且 Java 不允许创建泛型数组(因为类型参数是不可重现的)。

下面的代码是正确的(数组允许执行这些操作) ,因此需要未检查的警告:

public static <T> List<List<T>> createCombinations(List<T> ... lists) {
((Object[]) lists)[0] = new ArrayList<Integer>();
// place your code here
}

见综合解释 给你

正如上面提到的 janoh.janoh,Java 中的 varargs 只是数组的语法糖,加上在调用站点隐式创建数组。那么

List<List<String>> combinations =
Utils.createCombinations(cocNumbers, vatNumbers, ibans);

实际上

List<List<String>> combinations =
Utils.createCombinations(new List<String>[]{cocNumbers, vatNumbers, ibans});

但是你可能知道,由于许多其他问题的原因,在 Java 中不允许使用 new List<String>[],但是主要是因为数组在运行时知道它们的组件类型,并且在运行时检查添加的元素是否匹配它的组件类型,但是这种检查对于参数化类型是不可能的。

无论如何,编译器不会失败,它仍然创建数组:

List<List<String>> combinations =
Utils.createCombinations((List<String>[])new List<?>[]{cocNumbers, vatNumbers, ibans});

这可能是不安全的,但不一定是不安全的。大多数 varargs 方法只是迭代 varargs 元素并读取它们。在本例中,它不关心数组的运行时类型。这就是你的方法。因为使用的是 Java7,所以应该将 @SafeVarargs注释添加到方法中,这样就不会再收到这种警告。这个注释基本上是说,这个方法只关心元素的类型,而不是数组的类型。

但是,有些 varargs 方法确实使用数组的运行时类型。在这种情况下,它可能是不安全的。所以才会有警告。