web-dev-qa-db-fra.com

Varargs au problème ArrayList dans Java

Je ne comprends pas pourquoi les éléments suivants ne fonctionnent pas:

public void doSomething(int... args){
  List<Integer> broken = new ArrayList<Integer>(Arrays.asList(args))
}

Je crois comprendre que le compilateur convertit les "int ... args" en un tableau, donc le code ci-dessus devrait fonctionner.

Au lieu de travailler, je reçois:

symbole de symbole introuvable: constructeur ArrayList (Java.util.List<int[]>) emplacement: classe Java.util.ArrayList<Java.lang.Integer>

C'est bizarre. Je n'ajoute pas un tableau à la liste des tableaux, j'ajoute chaque élément de la liste à la liste des tableaux. Que se passe-t-il?

34
Ben B.

Java ne peut pas encadrer automatiquement un tableau, uniquement des valeurs individuelles. Je suggérerais de changer la signature de votre méthode en

public void doSomething(Integer... args)

Ensuite, l'autoboxing aura lieu lors de l'appel de doSomething, plutôt que d'essayer (et d'échouer) lors de l'appel de Arrays.asList.

Ce qui se passe est Java est maintenant en train de mettre automatiquement chaque valeur individuelle au fur et à mesure qu'elle est transmise à votre fonction. Ce que vous essayiez de faire auparavant était, en passant un int[] à Arrays.asList(), vous demandiez à cette fonction de faire l'autoboxing.

Mais l'autoboxing est implémenté par le compilateur - il voit que vous aviez besoin d'un objet mais que vous passiez une primitive, il a donc automatiquement inséré le code nécessaire pour le transformer en un objet approprié. La fonction Arrays.asList() a déjà été compilée et attend des objets, et le compilateur ne peut pas transformer un int[] en Integer[].

En déplaçant l'autoboxing vers les appelants de votre fonction, vous avez résolu ce problème.

43
Jonathan

Tu peux faire

public void doSomething(int... args){
    List<Integer> ints = new ArrayList<Integer>(args.length);
    for(int i: args) ints.add(i);
}

ou

public void doSomething(Integer... args){
    List<Integer> ints = Arrays.asList(args);
}
17
Peter Lawrey

Dans ce cas, l'autoboxing (conversion automatique de int en Integer) ne fonctionne pas. Vous devez ajouter chaque int manuellement à la liste.

Si vous avez souvent besoin de code comme celui-ci, pensez à utiliser commons lang qui a org.Apache.commons.lang.ArrayUtils.toObject(int[])

7
Aaron Digulla

Vous pouvez résoudre ce problème en utilisant la goyave:

List<Integer> broken = new ArrayList<>(Ints.asList(args))

Ou avec des flux:

List<Integer> broken = Arrays
    .stream(array)
    .boxed()
    .collect(Collectors.toCollection(ArrayList::new));
3
ZhekaKozlov