为什么java没有autobox int 到Integer
当我做以下,
-
arrayList1
– 包含一个元素,它是一个int[]
。 -
arrayList2
– 未编译(错误:构造函数ArrayList(List)
未定义) -
arrayList3
– 包含7个元素,它们是Integer
对象
这是代码:
int[] intArray = new int[]{2,3,4,5,6,7,8}; ArrayList arrayList1 = new ArrayList(Arrays.asList(intArray)); ArrayList arrayList2 = new ArrayList(Arrays.asList(intArray)); Integer[] integerArray = new Integer[]{2,3,4,5,6,7,8}; ArrayList arrayList3 = new ArrayList(Arrays.asList(integerArray));
问题:为什么编译器不会自动将int[]
中的元素添加到Integer
并创建ArrayList
? 这背后的原因是什么? 这是我的愚蠢还是其他原因?
区别在于int[]
本身是一个Object
,而Integer[]
是一个对Integer
对象的引用数组。
Arrays.asList(T...)
方法采用某些类型T
可变参数,没有上限。 该方法的擦除是Arrays.asList(Object...)
。 这意味着它将采用从Object
扩展的任何类型的可变数量的参数。
由于int
不是Object
,而是基本类型,因此它不能作为T[]
单个元素传递,而int[]
是Object
本身,它将作为T[]
数组的第一个元素( T...
内部只是T[]
。 但是, Integer[]
将作为T[]
传递, Integer[]
每个引用都作为T[]
不同参数传递。
即使您认为编译器应该完成从int[]
数组的每个元素到Integer
,这对编译器来说太过分了。 首先,它需要获取每个数组元素,并将其设置为Integer
,然后它需要在内部从这些元素创建一个Integer[]
。 那太过分了。 它已经从int[]
直接转换为Object
,后面是它。 虽然我一直希望Java允许从int[]
到Integer[]
隐式转换,但这样可以在使用generics时更简单,但同样,这就是语言的设计方式。
举一个简单的例子:
Object[] array = new Integer[10]; // this is valid conversion Object[] array2 = new int[10]; // this is not Object obj = new int[10]; // this is again a valid conversion
因此,在您的代码中, Arrays.asList(intArray)
返回一个ArrayList
而不是ArrayList
。 您不能将它传递给ArrayList
构造函数。
有关:
-
int[]
和Integer[]
:有什么区别?
int[]
与Integer[]
。
数组具有关联的Class对象。 原始int数组的类对象是[I
Integer
数组的类对象是[Ljava/lang/Integer
。
数组本身就是一个对象,因此在两个相同类型的对象之间进行转换是一种身份转换 。 两个不同的类型对象之间的转换不是 – 和int[]
和Integer[]
肯定是不同的,正如上面的字节码所certificate的那样。
最后,请记住,如果存在相关的拳击转换 ,则自动装箱仅适用。
从技术上讲,它当然可以做到。 然而,原始类型数组到包装器类型数组的自动装箱/拆箱比你期望的要多。
首先看看Java的自动装箱/拆箱:它的作用只是一种语法糖,可以帮助您输入原始包装器代码。 例如
Integer i = 10;
编译器知道它期望一个Integer
,但是int
存在。 因此编译器正在做的是将代码转换为:
Integer i = Integer.valueOf(10);
它对取消装箱做了类似的事情:当它在期望int
但是存在Integer
情况下,编译器将其替换为varName.intValue()
回到arrays。 我们可以预见两个问题:
第一个问题是,没有直接的方法可以从int数组转换为Integer数组。 您可能会争辩说编译器可以转换
int[] intArray = ....; Integer[] wrapperArray = intArray ;
至
Integer[] wrapperArray = new Integer[intArray.size()]; for (int i = 0; i < intArray.size(); i++) { wrapperArray[i] = Integer.valueOf(intArray[i]); }
但对于语法糖而言,这似乎太过分了。
第二个大问题是,当您将其作为参数传递给方法时,如果对数组进行自动装箱/取消装箱,而不是传递原始数组的引用,则现在传递原始数组副本的引用。 如果您要更改方法中的数组内容,原始数组将不会受到影响。 这可以带给你很多惊喜。
例如
void foo(Integer[] arr) { arr[0] = 0; } // invoking foo in some code: int[] intArr = new int[]{9,8,7,6}; foo(intArr); // intArr[0] will still be 9, instead of 0
因为int[]
和Integer[]
都是对象。 首先将保存原始int
值,它们不是Object
类型,而第二个将存储Integer
对象的引用,它们是Object
类型。
arrayList1
是一个大小为1的List。
arrayList1.size() = 1 arrayList3.size() = 7
int []被强制转换为单个Object。 该Object不能转换为Integer。
- Java – 在迭代时向列表添加元素
- Android Parcelable – 使用通用数据类型将数据读/写到Parcel
- 如何将ArrayList绑定到Oracle中的PreparedStatement?
- 迭代时出现Java“ConcurrentModificationException”运行时错误.next()
- Java 2D ArrayList和排序
- 两个线程访问经常更新的Arraylist的问题
- 如何在java中使用自定义类型ArrayList上的包含?
- JAXB封送由XmlAdapter创建的ArrayList
- 无法将String添加到ArrayList:“misplaced construct(s)”