1
Aprender a programar desde cero / Paso de objetos como parámetros en Java por referencia o por valor. Manipulación
« en: 23 de Marzo 2015, 15:46 »
Hola.
Hace tiempo que me ronda por la cabeza una duda que me plantean las opciones para pasar objetos como parámetros a las clases.
Me refiero a estas dos opciones.
La opción A: (asignación por igualdad)
public void setPersona(Persona persona1) {
persona = new Persona(persona1.getNombre(), persona1.getEdad());
}
No me plantea ninguna duda. La considero perfecta e incorruptible. Se puede perder el objeto persona1 pues ya ha dado una copia de sus datos.
La duda la tengo en esta opción B: (asignación por identidad)
public void setPersona(Persona persona1) {
persona = persona1;
}
Sobre esta opción he leido que si persona1 cambia más tarde, tal vez ¿? el objeto persona cambie en la misma forma sin haberlo decidido yo así.
He creado el código que adjunto en el mensaje intentando simular ese cambio inesperado, y he aquí la salida que obtengo:
Salida.txt
En la salida del programa presento en dos columnas los dos elementos de cada array: agente, perro y equipo creados. Cada clase tiene sus propios atributos y en la clase Equipo dos atributos son de tipo Agente y Perro.
En la clase Equipo el atributo de tipo Perro lo inicializo o modifico siempre con la opción A, citada arriba (establezco una asignación de igualdad), y el atributo de tipo Agente lo modifico con la opción B, (establezco siempre una asignación de identidad).
Cada vez que en la salida se muestra un objeto, adjunta va una referencia que Java crea única para ese objeto (es la respuesta que da el método toString(), no sobreescrito a propósito para poder mostrar esa información.)
Esto que yo llamo referencia, supongo que viene a ser una forma que tiene Java de ligar el objeto en cuestión con los datos de este objeto en la memoria. ¿?
Esta referencia cambia en cada ejecución (la memoria no debe ser igual en todo momento).
En la salida, hasta la línea 17 se crean y presentan los objetos.
En la línea 18 se modifican un objeto de tipo Agente y otro de tipo Perro.
Hasta la línea 32 se vuelven a mostrar todos los objetos.
En la línea 33 se vuelven a modificar los mismos objetos de tipo Agente y de tipo Perro.
Y hasta el final se vuelven a mostrar todos los objetos.
En la información mostrada, se observa lo siguiente:
El objeto pe[1] que no se ha modificado en ningún momento, mantiene sus atributos y su referencia en todo momento. Este mismo objeto al colocarlo dentro del objeto equipo, cambia su referencia y la mantiene siempre dentro del objeto equipo (pues su asignación ha sido por igualdad).
El objeto pe[0] al que se le han hecho cambios, cambia su contenido y también su referencia en cada cambio. Una vez este objeto se coloca dentro del objeto equipo, cambia su referencia y la mantiene junto con los datos.
El objeto ag[1] que no se ha modificado en ningún momento, mantiene su referencia incluso dentro del objeto equipo (pues su asignación es por identidad), tampoco cambian sus datos.
El objeto ag[0] al que se le han hecho cambios, cambia su contenido cada vez al igual que su referencia. Al colocarlo dentro del objeto equipo, mantiene sus datos en todo momento al igual que su referencia (que es la misma que en su creación antes de modificar el objeto).
El objeto eq[1] mantiene su referencia en todo momento aunque han cambiado algunas referencias internas. Nunca cambian los datos.
El objeto eq[0] mantiene su referencia en todo momento aunque cambian algunas referencias internas así como datos.
Conclusión:
No se pierden datos de objetos pasados como parámetros tanto si se usa la opción A -era previsible-, como la B -en la que tenía dudas-
Si existe el riesgo a que un atributo inicializado o actualizado con un objetoZ revierta su contenido al cambiar externamente el objetoZ debe ser a un nivel muy profundo y que yo no sé reproducir.
Os pido vuestros comentarios después de haber mascullado/triturado todo el mamotreto anterior. Gracias por vuestra opinión.
Saludos
Hace tiempo que me ronda por la cabeza una duda que me plantean las opciones para pasar objetos como parámetros a las clases.
Me refiero a estas dos opciones.
La opción A: (asignación por igualdad)
public void setPersona(Persona persona1) {
persona = new Persona(persona1.getNombre(), persona1.getEdad());
}
No me plantea ninguna duda. La considero perfecta e incorruptible. Se puede perder el objeto persona1 pues ya ha dado una copia de sus datos.
La duda la tengo en esta opción B: (asignación por identidad)
public void setPersona(Persona persona1) {
persona = persona1;
}
Sobre esta opción he leido que si persona1 cambia más tarde, tal vez ¿? el objeto persona cambie en la misma forma sin haberlo decidido yo así.
He creado el código que adjunto en el mensaje intentando simular ese cambio inesperado, y he aquí la salida que obtengo:
Salida.txt
Código: [Seleccionar]
Fecha: 23/03/2015 > 02:06:01
01) Creados agentes: ag[0] = new Agente("A00",30) y ag[1] = new Agente("A11",31)
02) ag[0]. ref.: ...Agente@143e87d ag[1]. ref.: ...Agente@1549b82
03) ····················idAgente: A00 ····················idAgente: A11
04) ···········ExperienciaPuntos: 30 ···········ExperienciaPuntos: 31
05) Creados perros: pe[0] = new Perro("Labrador",false) y pe[1] = new Perro("Dogo",true)
06) pe[0]. ref.: ...Perro@1ad81d2 pe[1]. ref.: ...Perro@262adc
07) ························Raza: Labrador ························Raza: Dogo
08) ················Esterilizado: false ················Esterilizado: true
09) Creados equipos: eq[0] = new Equipo("Equipo A",ag[0],pe[0]) y eq[1] = new Equipo("Mister T",ag[1],pe[1])
10) eq[0]<alias,ag,pe>. Ref.: ...Equipo@1c7d5b2 eq[1]<alias,ag,pe>. Ref.: ...Equipo@9e9a07
11) ·······················Alias: Equipo A ·······················Alias: Mister T
12) Ref. agente: ...Agente@143e87d Ref. agente: ...Agente@1549b82
13) ····················idAgente: A00 ····················idAgente: A11
14) ···········ExperienciaPuntos: 30 ···········ExperienciaPuntos: 31
15) Ref. perro: ...Perro@927633 Ref. perro: ...Perro@18e2a42
16) ························Raza: Labrador ························Raza: Dogo
17) ················Esterilizado: false ················Esterilizado: true
18) Asignación de identidad. ag[0] = ag[1] Asignación de identidad. pe[0] = pe[1]
19) ag[0]. ref.: ...Agente@1549b82 ag[1]. ref.: ...Agente@1549b82
20) ····················idAgente: A11 ····················idAgente: A11
21) ···········ExperienciaPuntos: 31 ···········ExperienciaPuntos: 31
22) pe[0]. ref.: ...Perro@262adc pe[1]. ref.: ...Perro@262adc
23) ························Raza: Dogo ························Raza: Dogo
24) ················Esterilizado: true ················Esterilizado: true
25) eq[0]<alias,ag,pe>. Ref.: ...Equipo@1c7d5b2 eq[1]<alias,ag,pe>. Ref.: ...Equipo@9e9a07
26) ·······················Alias: Equipo A ·······················Alias: Mister T
27) Ref. agente: ...Agente@143e87d Ref. agente: ...Agente@1549b82
28) ····················idAgente: A00 ····················idAgente: A11
29) ···········ExperienciaPuntos: 30 ···········ExperienciaPuntos: 31
30) Ref. perro: ...Perro@927633 Ref. perro: ...Perro@18e2a42
31) ························Raza: Labrador ························Raza: Dogo
32) ················Esterilizado: false ················Esterilizado: true
33) Objeto nuevo. ag[0] = new Agente() Objeto nuevo. pe[0] = new Perro()
34) ag[0]. ref.: ...Agente@1419cf7 ag[1]. ref.: ...Agente@1549b82
35) ····················idAgente: Sin Id ····················idAgente: A11
36) ···········ExperienciaPuntos: 0 ···········ExperienciaPuntos: 31
37) pe[0]. ref.: ...Perro@b44131 pe[1]. ref.: ...Perro@262adc
38) ························Raza: Desconocida ························Raza: Dogo
39) ················Esterilizado: false ················Esterilizado: true
40) eq[0]<alias,ag,pe>. Ref.: ...Equipo@1c7d5b2 eq[1]<alias,ag,pe>. Ref.: ...Equipo@9e9a07
41) ·······················Alias: Equipo A ·······················Alias: Mister T
42) Ref. agente: ...Agente@143e87d Ref. agente: ...Agente@1549b82
43) ····················idAgente: A00 ····················idAgente: A11
44) ···········ExperienciaPuntos: 30 ···········ExperienciaPuntos: 31
45) Ref. perro: ...Perro@927633 Ref. perro: ...Perro@18e2a42
46) ························Raza: Labrador ························Raza: Dogo
47) ················Esterilizado: false ················Esterilizado: true
En la salida del programa presento en dos columnas los dos elementos de cada array: agente, perro y equipo creados. Cada clase tiene sus propios atributos y en la clase Equipo dos atributos son de tipo Agente y Perro.
En la clase Equipo el atributo de tipo Perro lo inicializo o modifico siempre con la opción A, citada arriba (establezco una asignación de igualdad), y el atributo de tipo Agente lo modifico con la opción B, (establezco siempre una asignación de identidad).
Cada vez que en la salida se muestra un objeto, adjunta va una referencia que Java crea única para ese objeto (es la respuesta que da el método toString(), no sobreescrito a propósito para poder mostrar esa información.)
Esto que yo llamo referencia, supongo que viene a ser una forma que tiene Java de ligar el objeto en cuestión con los datos de este objeto en la memoria. ¿?
Esta referencia cambia en cada ejecución (la memoria no debe ser igual en todo momento).
En la salida, hasta la línea 17 se crean y presentan los objetos.
En la línea 18 se modifican un objeto de tipo Agente y otro de tipo Perro.
Hasta la línea 32 se vuelven a mostrar todos los objetos.
En la línea 33 se vuelven a modificar los mismos objetos de tipo Agente y de tipo Perro.
Y hasta el final se vuelven a mostrar todos los objetos.
En la información mostrada, se observa lo siguiente:
El objeto pe[1] que no se ha modificado en ningún momento, mantiene sus atributos y su referencia en todo momento. Este mismo objeto al colocarlo dentro del objeto equipo, cambia su referencia y la mantiene siempre dentro del objeto equipo (pues su asignación ha sido por igualdad).
El objeto pe[0] al que se le han hecho cambios, cambia su contenido y también su referencia en cada cambio. Una vez este objeto se coloca dentro del objeto equipo, cambia su referencia y la mantiene junto con los datos.
El objeto ag[1] que no se ha modificado en ningún momento, mantiene su referencia incluso dentro del objeto equipo (pues su asignación es por identidad), tampoco cambian sus datos.
El objeto ag[0] al que se le han hecho cambios, cambia su contenido cada vez al igual que su referencia. Al colocarlo dentro del objeto equipo, mantiene sus datos en todo momento al igual que su referencia (que es la misma que en su creación antes de modificar el objeto).
El objeto eq[1] mantiene su referencia en todo momento aunque han cambiado algunas referencias internas. Nunca cambian los datos.
El objeto eq[0] mantiene su referencia en todo momento aunque cambian algunas referencias internas así como datos.
Conclusión:
No se pierden datos de objetos pasados como parámetros tanto si se usa la opción A -era previsible-, como la B -en la que tenía dudas-
Si existe el riesgo a que un atributo inicializado o actualizado con un objetoZ revierta su contenido al cambiar externamente el objetoZ debe ser a un nivel muy profundo y que yo no sé reproducir.
Os pido vuestros comentarios después de haber mascullado/triturado todo el mamotreto anterior. Gracias por vuestra opinión.
Saludos