¿Cuál es la diferencia entre
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
2.List<Integer> list2 = Arrays.asList(ia);
donde ia
es una matriz de enteros.
He llegado a saber que algunas operaciones no están permitidas en list2
. ¿Por qué es así?
¿cómo se almacena en la memoria (referencias / copia)?
Cuando barajo las listas, list1
no afecta al array original pero list2
sí. Pero aún así list2
es algo confuso.
¿Cómo ArrayList
es upcasted a la lista difiere de la creación de nuevos ArrayList
?
list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Primero, veamos qué hace esto:
Arrays.asList(ia)
Toma un array ia
y crea una envoltura que implementa List<Integer>
, que hace que el array original esté disponible como lista. No se copia nada, sólo se crea un único objeto envoltorio. Las operaciones sobre la envoltura de lista se propagan al array original. Esto significa que si barajas la envoltura de la lista, el array original también se baraja, si sobrescribes un elemento, se sobrescribe en el array original, etc. Por supuesto, algunas operaciones de List
no están permitidas en la envoltura, como añadir o eliminar elementos de la lista, sólo puedes leer o sobrescribir los elementos.
Ten en cuenta que la envoltura de la lista no extiende ArrayList
- es un tipo diferente de objeto. Las ArrayList
s tienen su propio array interno, en el que almacenan sus elementos, y son capaces de redimensionar los arrays internos, etc. El wrapper no tiene su propio array interno, sólo propaga las operaciones al array que se le da.
Por otro lado, si posteriormente creas un nuevo array como
new ArrayList<Integer>(Arrays.asList(ia))
entonces creas un nuevo ArrayList
, que es una copia completa e independiente del original. Aunque aquí también se crea la envoltura utilizando Arrays.asList
, sólo se utiliza durante la construcción de la nueva ArrayList
y después se recoge la basura. La estructura de este nuevo ArrayList
es completamente independiente del array original. Contiene los mismos elementos (tanto el array original como este nuevo ArrayList
hacen referencia a los mismos enteros en memoria), pero crea un nuevo array interno que contiene las referencias. Así que cuando lo barajas, añades, eliminas elementos, etc., el array original no cambia.
Esto se debe a que ArrayList
resultante de Arrays.asList()
no es del tipo java.util.ArrayList
. Arrays.asList()
crea un ArrayList
de tipo java.util.Arrays$ArrayList
que no extiende java.util.ArrayList
sino que sólo extiende java.util.AbstractList
.
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
En este caso, list1
es de tipo ArrayList
.
List<Integer> list2 = Arrays.asList(ia);
Aquí, la lista se devuelve como una vista List
, lo que significa que sólo tiene los métodos adjuntos a esa interfaz. De ahí que algunos métodos no estén permitidos en list2
.
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Aquí, ESTÁS creando un nuevo ArrayList
. Simplemente le pasas un valor en el constructor. Esto no es un ejemplo de casting. En casting, podría verse más como esto:
ArrayList list1 = (ArrayList)Arrays.asList(ia);