Java unchecked: creación de matriz genérica sin marcar para el parámetro varargs


He configurado Netbeans para mostrar advertencias sin marcar en mi código Java, pero no entiendo el error en las siguientes líneas:

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

Da:

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

Método fuente:

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

¿Qué es exactamente lo que va mal y cómo lo arreglaría, ya que supongo que dejar advertencias sin verificar en el código no es una buena idea?

Olvidé mencionarlo, pero estoy usando Java 7.

Editar : También veo ahora que el método tiene la siguiente:

[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>...)
Author: skiwi, 2014-01-15

3 answers

Como janoh.janoh mencionado anteriormente, varargs en Java es solo un azúcar sintáctico para matrices más la creación implícita de una matriz en el sitio que llama. So

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

Es en realidad

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

Pero como puede saber, new List<String>[] no está permitido en Java, por razones que se han cubierto en muchas otras preguntas, pero principalmente tienen que ver con el hecho de que los arrays conocen su tipo de componente en tiempo de ejecución, y comprueban en tiempo de ejecución si los elementos agregados coinciden con su tipo de componente, pero esta comprobación no es posible para tipos parametrizados.

De todos modos, en lugar de fallar, el compilador todavía crea la matriz. Hace algo similar a esto:

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

Esto es potencialmente inseguro, pero no necesariamente inseguro. La mayoría de los métodos varargs simplemente iteran sobre los elementos varargs y los leen. En este caso, no le importa el tipo de tiempo de ejecución de la matriz. Este es el caso con su método. Dado que está en Java 7, debe agregar la anotación @SafeVarargs a su método, y no obtendrá esta advertencia nunca más. Esta anotación básicamente dice, este método solo se preocupa por los tipos de los elementos, no el tipo de la matriz.

Sin embargo, hay algunos métodos varargs que usan el tipo de tiempo de ejecución de la matriz. En este caso, es potencialmente inseguro. Por eso la advertencia está ahí.

 121
Author: newacct,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-15 23:42:13

Porque el compilador de java usa una creación de array implícita para varargs, y java no permite la creación de array genérico (porque el argumento type no es reifiable).

El siguiente código es correcto (estas operaciones se permiten con matrices), por lo que se necesita una advertencia sin marcar:

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

Ver una explicación completa aquí

 12
Author: Philip Voronov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-03 16:37:49

¿Cómo se suprime la advertencia?

@SuppressWarnings("unchecked")
 0
Author: V. Kalyuzhnyu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-16 13:46:29