español - java se 11
Por qué java no autobox int (5)
La diferencia es int[]
es un Object
, mientras que Integer[]
es una matriz de referencias al objeto Integer
.
Arrays.asList(T...)
toma argumentos variables de algún tipo T
sin límites superiores. La eliminación de ese método es Arrays.asList(Object...)
. Eso significa que tomará una cantidad variable de argumentos de cualquier tipo que se extienda desde Object
.
Como int
no es un Object
, sino un tipo primitivo, por lo que no se puede pasar como elemento individual de T[]
, mientras que int[]
es un Object
sí mismo, irá como primer elemento de la matriz T[]
( T...
internamente es un T[]
solamente). Sin embargo, Integer[]
pasará como T[]
, con cada referencia en Integer[]
pasado como argumento diferente a T[]
.
E incluso si argumentara que el compilador debería haber hecho la conversión de cada elemento de la matriz int[]
a Integer
, eso sería demasiado trabajo para el compilador. En primer lugar, necesitaría tomar cada elemento de la matriz y colocarlo en Integer
, luego necesitaría crear internamente un Integer[]
partir de esos elementos. Eso es realmente demasiado. Ya tiene una conversión directa de int[]
a Object
, que sigue. Aunque siempre he deseado que Java permitiera la conversión implícita de int[]
a Integer[]
, eso hubiera simplificado la vida al trabajar con genéricos, pero de nuevo, así es como se diseña el lenguaje.
Tome un ejemplo simple:
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
Entonces, en su código Arrays.asList(intArray)
devuelve una ArrayList<int[]>
y no una ArrayList<Integer>
. No puede pasarlo al constructor ArrayList<Integer>()
.
Relacionado:
-
int[]
eInteger[]
: ¿Cuál es la diferencia?
Cuando hago lo siguiente,
-
arrayList1
- contiene un elemento y es unint[]
. -
arrayList2
- no compilando (Error: el constructorArrayList<Integer>(List<int[]>)
no está definido) -
arrayList3
- contiene 7 elementos y son objetosInteger
Aquí está el código:
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));
Pregunta: ¿Por qué el compilador no coloca automáticamente los elementos en el int[]
en Integer
y crea una ArrayList<Integer>
? Cuál es la razón detrás de esto? ¿Es esa mi estupidez o alguna otra razón?
Porque int[]
e Integer[]
ambos son objetos. Primero mantendrá valores primitivos int
, que no son del tipo Object
mientras que el segundo almacenará referencias de objetos Integer
, que son de tipo Object
.
Técnicamente es posible hacerlo, por supuesto. Sin embargo, el autoboxing / unboxing de la matriz tipo primitiva a la matriz tipo wrapper es más de lo que esperaba.
Primero mira en el auto-boxing / unboxing de Java: lo que hace es simplemente un azúcaro de sintaxis para salvarte escribiendo el código de envoltura primitivo. p.ej
Integer i = 10;
El compilador sabe que está esperando un Integer
, pero int
presente en su lugar. Por lo tanto, lo que el compilador está haciendo es traducir su código a:
Integer i = Integer.valueOf(10);
Hace algo similar para unboxing: cuando se encuentra en una situación que espera int
pero está presente Integer
, el compilador lo reemplaza con varName.intValue()
De vuelta a la matriz. Hay dos problemas que podemos prever:
El primer problema es que no hay una forma directa de transformar de una matriz int a una matriz Integer. Usted puede argumentar que el compilador puede transformar
int[] intArray = ....;
Integer[] wrapperArray = intArray ;
a
Integer[] wrapperArray = new Integer[intArray.size()];
for (int i = 0; i < intArray.size(); i++) {
wrapperArray[i] = Integer.valueOf(intArray[i]);
}
pero eso parece demasiado para una sintaxis de azúcar.
El segundo gran problema es que cuando lo pasas como un parámetro a un método, si ocurre el autoboxing / unboxing para la matriz, en lugar de pasar la referencia de la matriz original, ahora estás pasando la referencia de una copia de la matriz original. En caso de que esté cambiando el contenido de la matriz en su método, la matriz original no se verá afectada. Eso puede traerte muchas sorpresas.
p.ej
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
Un int[]
no es lo mismo que un Integer[]
.
Una matriz tiene como objeto de Clase asociado. El objeto de clase para una matriz de entradas primitivas es [I
El objeto de clase para una matriz de Integer
es [Ljava/lang/Integer
.
Una matriz es en sí misma un objeto, por lo que la conversión entre dos objetos del mismo tipo es una conversión de identidad . La conversión entre dos objetos tipados diferentes no es - e int[]
e Integer[]
son definitivamente diferentes, como lo demuestra el bytecode anterior.
Por último, tenga en cuenta que el autoboxing solo se aplicaría realmente si hubiera una conversión de boxeo asociada .
arrayList1
es realmente una lista de tamaño uno.
arrayList1.size() = 1
arrayList3.size() = 7
El int [] está siendo lanzado a un solo objeto. Ese objeto no se puede convertir a Entero.