web-dev-qa-db-fra.com

Java décoché: création d'un tableau générique décochée pour le paramètre varargs

J'ai configuré Netbeans pour afficher des avertissements non vérifiés dans mon code Java, mais je ne comprends pas l'erreur sur les lignes suivantes:

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

Donne:

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

Méthode 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;
}

Qu'est-ce qui ne va pas et comment puis-je résoudre le problème, car je suppose que laisser des avertissements non vérifiés dans le code n'est pas une bonne idée?

Oublié de mentionner, mais j'utilise Java 7.

Edit: Je vois aussi maintenant que la méthode a les caractéristiques suivantes:

[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>...)
91
skiwi

Comme janoh.janoh mentionné ci-dessus, varargs in Java n'est qu'un sucre syntaxique pour les tableaux, plus la création implicite d'un tableau sur le site appelant.

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

est en fait

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

Mais comme vous le savez peut-être, new List<String>[] n’est pas autorisé en Java, pour des raisons qui ont été abordées dans de nombreuses autres questions, mais qui sont principalement liées au fait que les tableaux connaissent leur type de composant au moment de l’exécution et vérifient au moment de l’exécution si les éléments ajoutés correspondent à son type de composant. check n'est pas possible pour les types paramétrés.

Quoi qu'il en soit, plutôt que d’échouer, le compilateur crée toujours le tableau. Il fait quelque chose de similaire à ceci:

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

Ceci est potentiellement dangereux, mais pas nécessairement dangereux. La plupart des méthodes varargs parcourent simplement les éléments varargs et les lisent. Dans ce cas, le type d’exécution de la matrice ne s’intéresse pas. C'est le cas avec votre méthode. Puisque vous êtes sur Java 7, vous devriez ajouter le @SafeVarargs annotation à votre méthode et vous ne recevrez plus cet avertissement. Cette annotation dit en gros que cette méthode ne concerne que les types des éléments, pas le type du tableau.

Cependant, certaines méthodes varargs utilisent le type d'exécution du tableau. Dans ce cas, il est potentiellement dangereux. C'est pourquoi l'avertissement est là.

145
newacct

Parce que Java utilise une création de tableau implicite pour varargs, et Java n'autorise pas la création de tableaux génériques (car l'argument de type n'est pas réifiable).

Le code ci-dessous est correct (ces opérations sont autorisées avec des tableaux), un avertissement non vérifié est donc nécessaire:

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

Voir une explication complète ici

13
Philip Voronov