Java中将Varargs转换为ArrayList的问题

59

我不明白为什么以下代码不起作用:

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>

这很奇怪。我并没有将数组添加到ArrayList中,而是将列表中的每个元素添加到ArrayList中。发生了什么?


因为你正在创建 List<int[]>,所以将 int... args 改为 Integer... args 可能会有好运。 - bestsss
4个回答

60

Java无法自动装箱数组,只能处理单个值。建议您将方法签名更改为

public void doSomething(Integer... args)

当调用doSomething函数时,自动装箱将发生,而不是在调用Arrays.asList时尝试(并失败)。

发生的是Java现在自动装箱每个传递给函数的值。之前您尝试的是通过将int[]传递给Arrays.asList(),您要求该函数执行自动装箱。

但是,自动装箱是由编译器实现的--它看到您需要一个对象,但是正在传递一个原始数据类型,因此自动插入必要的代码将其转换为适当的对象。 Arrays.asList()函数已经编译并且期望对象,编译器无法将int[]转换为Integer[]

通过将自动装箱移动到函数的调用者,您解决了这个问题。


哦!好的。不过,你能解释一下为什么吗?我猜当你将一个集合传递给ArrayList时,在幕后每个元素都会被添加到ArrayList中(尽管现在我想想,ArrayList可能只是某个集合的视图)。如果你能启发我一下就太感谢了!谢谢。 - Ben B.
@Ben B,它与addAll()用于集合或putAll()用于Map做的事情大致相同。 - Peter Lawrey
我知道addAll()的作用,但不知道它是如何实现的。 - Ben B.
基本上就是 Object[] a = c.toArray();System.arraycopy(a, 0, elementData, size, numNew);,其中 c 是集合,elementData 是 ArrayList 的后备数组。 - Thomas
@jonathan“但是装箱是由编译器实现的-它看到你需要一个对象,但是却传递了一个原始类型”(摘自您的答案)。int []不是一个对象吗?因为我知道数组是对象。 - JAVA
显示剩余2条评论

31

你可以这样做

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

10

你可以使用Guava解决这个问题:

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

或者使用流的方式:

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

boxed() 是一个不错的解决方案。 - Pampa Nello

8
在这种情况下,自动装箱(从int到Integer的自动转换)不起作用。您必须手动将每个int添加到列表中。
如果您经常需要这样的代码,请考虑使用commons lang,它具有org.apache.commons.lang.ArrayUtils.toObject(int[])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接