Проблема Varargs to ArrayList в Java - PullRequest
32 голосов
/ 18 марта 2011

Я не понимаю, почему не работает следующее:

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

Насколько я понимаю, компилятор преобразует "int ... args" в массив, поэтому приведенный выше код должен работать.

Вместо работы я получаю:

не может найти символ символ: конструктор ArrayList (java.util.List <int[]>) расположение: класс java.util.ArrayList <java.lang.Integer>

Это странно. Я не добавляю массив в список массивов, я добавляю каждый элемент из списка в массив. Что происходит?

Ответы [ 4 ]

40 голосов
/ 18 марта 2011

Java не может автоматически блокировать массив, только отдельные значения. Я бы предложил изменить подпись вашего метода на

public void doSomething(Integer... args)

Тогда будет происходить автобокс при вызове doSomething, вместо попытки (и сбоя) при вызове Arrays.asList.

То, что происходит, - это то, что Java теперь автоматически блокирует каждое отдельное значение, когда оно передается вашей функции. То, что вы пытались сделать раньше, это, передавая int[] в Arrays.asList(), вы просили эту функцию выполнить автобокс.

Но автобокс реализован компилятором - он видит, что вам нужен объект, но передает примитив, поэтому он автоматически вставляет необходимый код, чтобы превратить его в соответствующий объект. Функция Arrays.asList() уже скомпилирована и ожидает объекты, и компилятор не может превратить int[] в Integer[].

Переместив автобокс в вызывающие функции, вы решили эту проблему.

16 голосов
/ 18 марта 2011

Вы можете сделать

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

или

public void doSomething(Integer... args){
    List<Integer> ints = Arrays.asList(args);
}
7 голосов
/ 18 марта 2011

В этом случае автобокс (автоматическое преобразование из int в Integer) не работает.Вы должны добавить каждый int вручную в список.

Если вам часто нужен такой код, рассмотрите возможность использования commons lang , который имеет org.apache.commons.lang.ArrayUtils.toObject(int[])

3 голосов
/ 29 ноября 2017

Вы можете решить эту проблему, используя Guava:

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

Или с потоками:

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