ArrayList que modifica el valor devuelto por el método "get"
Tengo por debajo de dos situaciones relacionadas con el método ArrayList get
, una con la clase personalizada y otra con la clase String:
1. A continuación se muestra el ejemplo de la modificación de la clase Custom ArrayList elemento:
- Android uiautomator runtest error no encontró clase
- Editar texto aceptar sólo números no números decimales en android
- Uso de OpenGL para reemplazar Canvas - Android
- ¿Cómo obtener el idioma del teléfono con libgdx?
- ¿hay un acceso directo en eclipse para generar recursos (constructores, get / set ...)
ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>(); MyClass myObj1 = new MyClass(10); mTmpArray1.add(myObj1); MyClass myObj2 = mTmpArray1.get(0); myObj2.myInt = 20; MyClass myObj3 = mTmpArray1.get(0); Log.d(TAG, "Int Value:"+myObj3.myInt); // Prints "20"
2. A continuación se muestra el ejemplo de la modificación del elemento String ArrayList:
ArrayList<String> mTmpArray2 = new ArrayList<String>(); mTmpArray2.add("Test_10"); String myStr1 = mTmpArray2.get(0); myStr1 = "Test_20"; String myStr2 = mTmpArray2.get(0); Log.d(TAG, "Str Value:"+myStr2); // Prints "Test_10"
Así que en el caso de MyClass ArrayList, cuando llamo a get
y modificar el valor, entonces veo el cambio está reflejando cuando vuelva a get
.
Pero de la misma manera cuando modifico String ArrayList, entonces los cambios no están reflejando.
¿Cuál es la diferencia en el método get
en ambos escenarios?
¿Es que en el caso de String, la clase String crea una copia profunda y devuelve un nuevo objeto, y en caso de que la clase personalizada se cree poco profunda?
En el primer escenario aplicable a "LinkedHashMap", "HashMap" y "List"?
- Time.toMillis (boolean) no factor en la zona horaria
- Plaza en blanco en Google Maps
- Cómo crear getters y setters de Java cuando la clave del objeto es el número
- La aplicación de fuente de una línea que utiliza la vinculación de datos de Android-M no funciona
- FPS malo en el juego 2D android / java en dispositivos de alta definición
- Fuente no encontrada Android?
- Búsqueda de diseños por ID
- Manejo de eventos de aplicaciones de Android
No estás haciendo lo mismo en los dos casos.
Aquí se actualiza el estado de un objeto, por lo que el cambio afecta al objeto almacenado en la lista:
myObj2.myInt = 20;
Aquí se asigna un nuevo objeto a una variable local, por lo que la lista no se ve afectada:
myStr1 = "Test_20";
Si String
era mutable, podría haber modificado la String llamando a algún método, y el cambio se habría reflejado en el objeto almacenado en la lista:
myStr1.setSomething(...);
Por otro lado, si en el primer caso hubiera cambiado el valor de la variable local, el objeto almacenado en la lista no se habría visto afectado:
myObj2 = new MyClass (...);
Las cadenas son inmutables. No va a insertar la nueva cadena en la lista de matrices.
Cuando haces String myStr2 = mTmpArray2.get(0);
, Incluso si estás apuntando a una referencia en ArrayList, cualquier intento de cambiar el valor, (debido a la inmutabilidad de String) creará una nueva String (myStr2) que no hará referencia a ArrayList.
Cuando haces myStr1 = "xxx"
, en realidad no estás cambiando la referencia ArrayList, estás cambiando una nueva (copia) (ahora llamada myStr1) que fue agarrada de la ArrayList y tiene un ámbito local.
Lea más sobre Strings: Immutability of Strings en Java
Ahora, en el primer ejemplo, está señalando un objeto mutable (su clase personalizada) para que cambie literalmente el valor directo, a través de la referencia. Bienvenido a Java. 😉
Sin relación : Este código: MyClass myObj1 = new MyClass(10);
Es (discutible) considerado malo. Es mejor usar un patrón de fábrica que es mucho más fácil de leer. En otras palabras, los constructores públicos con parámetros son difíciles de leer (por ejemplo, no tengo idea de lo que estoy construyendo cuando leo su código).
Un enfoque (quizás) mejor sería: MyClass myObj = MyClass.createInstanceWithCapacity(10); // i've invented the name because I don't know what your 10 is, but look at both, which one do you think is easier to understand upon first glance?
MyClass myObj = MyClass.createInstanceWithCapacity(10); // i've invented the name because I don't know what your 10 is, but look at both, which one do you think is easier to understand upon first glance?
Descargo de responsabilidad : El comentario no relacionado anterior es mi opinión personal y no todos los desarrolladores estarán de acuerdo. 😉
Cuerdas tienen propiedad muy agradable llamado "Immutablity"
Esto significa que String no puede ser mutable (cambiado), cuando creamos / intentamos referirnos a la cadena antigua, se crea una nueva cadena de instancia. Y los cambios que hacemos se guardan en una nueva instancia y no afectan a la antigua cadena
Por ejemplo,
String s = "Old String"; System.out.println("Old String : "+s); // output : Old String String s2 = s; s2 = s2.concat(" made New"); System.out.println("New String : "+s2); // output : Old String made New System.out.println("Old String is not changed : "+s); // output : Old String
Éstas no son ninguna diferencia entre las dos llamadas "get". La diferencia está entre los tipos que el ArrayList mantiene, y lo que está haciendo las referencias que el método "get" devuelve.
En tu primer ejemplo, haz esto:
MyClass myObj2 = mTmpArray1.get(0); myObj2.myInt = 20;
Aquí, obtendrá una referencia a la instancia de MyClass en ArrayList en la posición 0 y está modificando un campo dentro de esta instancia.
En su segundo ejemplo, usted hace esto:
String myStr1 = mTmpArray2.get(0); myStr1 = "Test_20";
Aquí, obtendrá una referencia a la instancia String en la lista de matrices y, a continuación, le dará a myStr1 una referencia a una cadena diferente que cree ("Test_20"). Es como si escribieras myObj2 = new MyClass(20);
En la 2ª línea del primer ejemplo.
Por lo tanto, en resumen, en el primer ejemplo, se accede a un campo dentro del objeto mediante la alteración de la referencia que agarró. En el segundo ejemplo, simplemente cambió su referencia a punto en una cadena diferente.
También debo mencionar que en Java, cadenas son inmutables, es decir, una vez que han sido creados, no se puede cambiar.
String es una clase inmutable. Una línea como
myStr1 = "Test_20";
No cambia el valor del objeto String al que myStr1
apunta. En su lugar, se crea una nueva String y myStr1
se modifica para apuntar a la nueva String. El String original no cambia y se puede recuperar de ArrayList.
Su objeto MyClass
es claramente mutable. Sólo se crea una instancia y su estado se cambia por la asignación
myObj2.myInt = 20;
Por lo tanto, cuando este objeto se recupera de la ArrayList, su nuevo estado se ve.
Simplemente NO cambie la lista en su segundo ejemplo.
En el primer ejemplo, estás haciendo esto:
- Obtenga el primer objeto de la lista y guárdelo en la variable llamada 'myObj2'
- Modifique el objeto almacenado en la variable 'myObj2' estableciendo el valor int de este objeto
Pero su segundo ejemplo es completamente diferente:
String myStr1 = mTmpArray2.get(0); myStr1 = "Test_20";
Permítanme traducir eso:
- Obtenga el primer elemento de la lista y guárdelo en la variable llamada 'myStr1'.
- Establezca el valor de la variable 'myStr1' en "Test_20"
Por lo tanto, en caso de que esté modificando una variable del objeto almacenado en la lista. En caso de que usted está recuperando el objeto almacenado en la lista – y luego reutilizar la variable que ha almacenado ese objeto recuperado y utilizarlo para algo nuevo – pero eso no cambia la lista original, por supuesto.
Para modificar su lista para un tipo como cadena, necesitaría usar set (x, "Test_20").
- El texto de Android TextView no aparece en los dispositivos Samsung
- ¿Por qué el método onCreateOptionsMenu de Android devuelve super.onCreateOptionsMenu?