Проблема Varargs с ArrayList в Java
Я не понимаю, почему следующее не работает:
public void doSomething(int... args){
List<Integer> broken = new ArrayList<Integer>(Arrays.asList(args))
}
Его понимание того, что компилятор преобразует "int... args" в массив, поэтому приведенный выше код должен работать.
Вместо работы я получаю:
не может найти символ symbol: конструктор ArrayList (java.util.List <int[]
> ) местоположение: класс java.util.ArrayList <java.lang.Integer
>
Это странно. Я не добавляю массив в список массивов, я добавляю каждый элемент из списка в arraylist. Что происходит?
Ответы
Ответ 1
Java не может автоблокировать массив, а только отдельные значения. Я бы предложил изменить вашу подпись метода на
public void doSomething(Integer... args)
Тогда автобоксинг будет выполняться при вызове doSomething
, а не при попытке (и сбое) при вызове Arrays.asList
.
Что происходит, Java теперь автоматически устанавливает каждое отдельное значение, поскольку оно передается вашей функции. То, что вы пытались сделать раньше, было, передав int[]
to Arrays.asList()
, вы просили эту функцию выполнять автобоксинг.
Но автообъект реализуется компилятором - он видит, что вам нужен объект, но передавал примитив, поэтому он автоматически вставил необходимый код, чтобы превратить его в соответствующий объект. Функция Arrays.asList()
уже скомпилирована и ожидает объекты, а компилятор не может превратить int[]
в Integer[]
.
Переместив автобоксинг на вызывающих абонентов вашей функции, вы решили эту проблему.
Ответ 2
Вы можете сделать
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);
}
Ответ 3
В этом случае автобоксинг (автоматическое преобразование от int
до Integer
) не работает. Вы должны добавить каждый int
вручную в список.
Если вам нужен такой код часто, подумайте об использовании commons lang, у которого org.apache.commons.lang.ArrayUtils.toObject(int[])
Ответ 4
Вы можете решить эту проблему с помощью Guava:
List<Integer> broken = new ArrayList<>(Ints.asList(args))
Или с потоками:
List<Integer> broken = Arrays
.stream(array)
.boxed()
.collect(Collectors.toCollection(ArrayList::new));