简体   繁体   English

为什么java没有autobox int []到Integer []

[英]Why java does not autobox int[] to Integer[]

When I do the following, 当我做以下,

  • arrayList1 - contains one element and it is an int[] . arrayList1 - 包含一个元素,它是一个int[]
  • arrayList2 - not compiling (Error : The constructor ArrayList<Integer>(List<int[]>) is undefined) arrayList2 - 未编译(错误:构造函数ArrayList<Integer>(List<int[]>)未定义)
  • arrayList3 - contains 7 elements and they are Integer objects arrayList3 - 包含7个元素,它们是Integer对象

Here's the code: 这是代码:

int[] intArray = new int[]{2,3,4,5,6,7,8};
ArrayList arrayList1 = new ArrayList(Arrays.asList(intArray));
ArrayList<Integer> arrayList2 = new ArrayList<Integer>(Arrays.asList(intArray));

Integer[] integerArray = new Integer[]{2,3,4,5,6,7,8};
ArrayList<Integer> arrayList3 = new ArrayList<Integer>(Arrays.asList(integerArray));

Question : Why doesn't the compiler auto-box the elements in the int[] to Integer and create an ArrayList<Integer> ? 问题:为什么编译器不会自动将int[]中的元素装入Integer并创建ArrayList<Integer> What is the reason behind this? 这背后的原因是什么? Is that my stupidity or some other reason? 这是我的愚蠢还是其他原因?

The difference is int[] is itself an Object , whereas Integer[] is an array of references to Integer object. 区别在于int[]本身就是一个Object ,而Integer[]是一个对Integer对象的引用数组。

Arrays.asList(T...) method takes variable arguments of some type T with no upper bounds. Arrays.asList(T...)方法采用某些类型T可变参数,没有上限。 The erasure of that method is Arrays.asList(Object...) . 该方法的擦除是Arrays.asList(Object...) That means it will take variable number of arguments of any type that extends from Object . 这意味着它将采用从Object扩展的任何类型的可变数量的参数。

Since int is not an Object , but a primitive type, so it can't be passed as individual element of T[] , whereas int[] is an Object itself, it will go as first element of the T[] array ( T... internally is a T[] only). 由于int不是Object ,而是基本类型,因此它不能作为T[]单个元素传递,而int[]Object本身,它将作为T[]数组的第一个元素( T...内部只是T[] However, Integer[] will be passed as T[] , with each reference in Integer[] passed as different argument to T[] . 然而, Integer[]也将被传递T[]在每个参考Integer[]通过作为不同的参数T[]

And even if you would argue that compiler should have done the conversion from each element of int[] array to Integer , well that would be too much work for the compiler. 即使您认为编译器应该已经完成​​从int[]数组的每个元素到Integer ,这对编译器来说太过分了。 First it would need to take each array element, and box it to Integer , then it would need to internally create an Integer[] from those elements. 首先,它需要获取每个数组元素,并将其IntegerInteger ,然后它需要在内部从这些元素创建一个Integer[] That is really too much. 真的太多了。 It already has a direct conversion from int[] to Object , which it follows. 它已经从int[]直接转换为Object ,后面是它。 Although I have always wished Java allowed implicit conversion from int[] to Integer[] , that would have made life simpler while working with generics, but again, that's how the language is designed. 虽然我一直希望Java允许从int[]Integer[]隐式转换,但这样可以在使用泛型时简化生活,但同样,这就是语言的设计方式。

Take a simple example: 举一个简单的例子:

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

So, in your code Arrays.asList(intArray) returns a ArrayList<int[]> and not ArrayList<Integer> . 因此,在您的代码中, Arrays.asList(intArray)返回一个ArrayList<int[]>而不是ArrayList<Integer> You can't pass it to the ArrayList<Integer>() constructor. 您不能将它传递给ArrayList<Integer>()构造函数。


Related: 有关:

An int[] is not the same as an Integer[] . 一个int[]一样的Integer[]

An array has as associated Class object. 数组具有关联的Class对象。 The class object for an array of primitive ints is [I . 原始int数组的类对象是[I The class object for an array of Integer is [Ljava/lang/Integer . Integer数组的类对象是[Ljava/lang/Integer

An array is itself an object, so converting between two objects of the same type is an identity conversion . 数组本身就是一个对象,因此在两个相同类型的对象之间进行转换是一种身份转换 Converting between two different typed objects isn't - and int[] and Integer[] are definitely different, as evidenced by the bytecode above. 在两个不同的类型对象之间进行转换不是 - 而int[]Integer[]肯定是不同的,正如上面的字节码所证明的那样。

Lastly, bear in mind that autoboxing would only really apply if there was an associated boxing conversion . 最后,请记住,如果存在相关的拳击转换 ,则自动装箱仅适用。

Technically it is possible to do it of course. 从技术上讲,它当然可以做到。 However autoboxing/unboxing of primitive type array to wrapper type array is more than what you expect. 然而,原始类型数组到包装器类型数组的自动装箱/拆箱比你期望的要多。

First look into the auto-boxing/unboxing of Java: What it does is simply a syntax sugar to save you typing the primitive wrapper code. 首先看一下Java的自动装箱/拆箱:它的作用仅仅是一种语法糖,可以帮助您输入原始包装器代码。 eg 例如

Integer i = 10;

Compiler knows that it is expecting an Integer , but int present instead. 编译器知道它期望一个Integer ,但是int存在。 Therefore what the compiler doing is translating your code to: 因此编译器正在做的是将代码转换为:

Integer i = Integer.valueOf(10);

It does similar thing for unboxing: when in situation that it expects int but Integer is present, compiler replace it with varName.intValue() 它对取消装箱做了类似的事情:当它在期望int但是存在Integer情况下,编译器将其替换为varName.intValue()

Back to array. 回到阵列。 There are two problems we can forsee: 我们可以预见到两个问题:

The first problem is, there is no straight-forward way to transform from an int array to an Integer array. 第一个问题是,没有直接的方法可以从int数组转换为Integer数组。 You may argue that the compiler can transform 您可能会争辩说编译器可以转换

int[] intArray = ....;
Integer[] wrapperArray = intArray ;

to

Integer[] wrapperArray = new Integer[intArray.size()];
for (int i = 0; i < intArray.size(); i++) {
   wrapperArray[i] = Integer.valueOf(intArray[i]);
}

but that seems too much for a syntax sugar. 但对于语法糖而言,这似乎太过分了。

The second big problem is, when you are passing it as a parameter to a method, if autoboxing/unboxing happens for array, instead of reference of original array is passed, you are now passing the reference of a copy of the original array. 第二个大问题是,当您将其作为参数传递给方法时,如果对数组进行自动装箱/取消装箱,而不是传递原始数组的引用,则现在传递原始数组副本的引用。 In case you are changing the content of array in your method, the original array will not be affected. 如果您要更改方法中的数组内容,原始数组将不会受到影响。 That can bring you lots of surprises. 这可以带给你很多惊喜。

eg 例如

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

Because int[] and Integer[] both are objects. 因为int[]Integer[]都是对象。 First will hold primitive int values, which are not of type Object while second will store references of Integer objects, which are of type Object . 首先将保存原始int值,它们不是Object类型,而第二个将存储Integer对象的引用,它们是Object类型。

arrayList1 is really a List of size one. arrayList1是一个大小为1的List。

http://ideone.com/w0b1vY http://ideone.com/w0b1vY

arrayList1.size() = 1
arrayList3.size() = 7

The int[] is being cast to a single Object. int []被强制转换为单个Object。 That Object cannot be cast to Integer. 该Object不能转换为Integer。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM