Hola toni, no sé si voy a ser capaz de responder a todas las cuestiones que puedan surgir, aunque podemos intentarlo.
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í.
Sí, es tal como comentas. No es cuestión de que decidas o no decidas, sino simplemente de que se trata de referencias a un mismo espacio de memoria, un mismo objeto. Por eso si cambia el objeto, ambas referencias reflejarán dicho cambio (esto puede parecer algo involuntario en el sentido de que el cambio lo origina una de las referencias, pero afecta a ambas, en ese sentido se puede decir que hace algo que no has decidido, pero esto es una forma de hablar).
Una cosa que observo es que estás prestando atención a la referencia que devuelve el método toString() cuando no lo has sobreescrito. Por ejemplo Agente@d09ad0 como referencia de un agente. No creo que sea buena idea en el sentido de que esta referencia es algo propio de la operación interna del compilador y de la gestión de memoria que haga java, por tanto algo que no podemos controlar y algo que diríamos "impredecible". Por ejemplo, supongamos que un objeto tiene como referencia Agente@d09ad0. Dicha referencia no es controlada por nosotros ni sabemos los mecanismos que la controlan, por tanto podría cambiar arbitrariamente según cierta lógica que desconocemos. Si usamos esta referencia para programar o analizar lo que ocurre es posible que no obtengamos resultados coherentes (o quizás sí, de ahí que no me parezca buena idea su uso).
He creado un pequeño código de prueba:
public class Test {
public static void main (String[] args) {
Agente ag1 = new Agente("id1", 33);
Agente ag2 = new Agente("id2", 44);
System.out.println ("Antes de establecer identidad:\n"+ag1 + "\n"+ag2);
System.out.println ("Antes de establecer identidad el agente1 tiene puntos: "+ag1.getExperienciaPuntos());
ag1=ag2;
System.out.println ("Después de establecer identidad:\n"+ag1 + "\n"+ag2);
System.out.println ("Después de establecer identidad el agente1 tiene puntos: "+ag1.getExperienciaPuntos());
System.out.println ("Ahora modificamos el agente 2 y establecemos que tiene 220 puntos");
ag2.setExperienciaPuntos(220);
System.out.println ("Ahora el agente1 tiene puntos: "+ag1.getExperienciaPuntos());
System.out.println ("Ahora el agente2 tiene puntos: "+ag2.getExperienciaPuntos());
}
} // Fin de la clase TestEquipo
El resultado de ejecución es este:
Antes de establecer identidad:
Agente@10079c0
Agente@11ecbae
Antes de establecer identidad el agente1 tiene puntos: 33
Después de establecer identidad:
Agente@11ecbae
Agente@11ecbae
Después de establecer identidad el agente1 tiene puntos: 44
Ahora modificamos el agente 2 y establecemos que tiene 220 puntos
Ahora el agente1 tiene puntos: 220
Ahora el agente2 tiene puntos: 220
Lo veo todo coherente. Una vez establecida la relación de identidad, da igual qué referencia modifiquemos, que al estar apuntando ambas referencias al mismo objeto, las dos referencias quedan modificadas.
Ahora tendríamos otro punto de análisis: el paso de objetos como parámetros
Java es un poco especial porque cuando pasas un objeto no pasas el objeto en sí, sino una referencia (a la posición de memoria) del objeto.
Copio desde otro hilo:
PREGUNTA: ¿Los parámetros en Java se pasan por valor o por referencia? (Diferencia entre ambos sistemas discutida en
http://aprenderaprogramar.com/index.php?option=com_content&view=article&id=144:modulos-genericos-y-paso-de-parametros-por-valor-byval-o-por-referencia-byref-ejemplos-cu00207a&catid=36:curso-qbases-de-la-programacion-nivel-iiq&Itemid=60 y siguientes entregas de ese curso)
RESPUESTA:
A veces se piensa erróneamente que los tipos primitivos pasan por valor y los objetos por referencia, pero esto no es así. Todo parámetro pasa por valor.
La confusión radica en que cuando pasamos un tipo primitivo, este no es modificable dentro del método. En cambio, al pasar un objeto, sí se pueden producir modificaciones dentro del método. Pero la realidad es que cuando pasamos el parámetro no pasamos el objeto en sí, sino una referencia al objeto, y esta referencia es la que pasa por valor y funciona como una copia dentro del método, resultando que los cambios dentro del método no son conocidos luego fuera de él.
He hecho este pequeño código de prueba:
public class Test2 {
public static void main (String[] args) {
Agente ag1 = new Agente("id1", 33);
Agente ag2 = new Agente("id2", 44);
System.out.println ("Ahora el agente1 tiene puntos: "+ag1.getExperienciaPuntos());
System.out.println ("Ahora el agente2 tiene puntos: "+ag2.getExperienciaPuntos());
System.out.println ("Pasamos al agente 1 como parámetro a probarAsignar y lo modificamos ");
probarAsignar(ag1);
System.out.println ("Ahora el agente1 tiene puntos: "+ag1.getExperienciaPuntos());
System.out.println ("Esto ocurre porque lo que se pasa es una copia de la referencia");
System.out.println ("Pasamos al agente 1 como parámetro a probarModificar y lo modificamos ");
probarModificar(ag1);
System.out.println ("Ahora el agente1 tiene puntos: "+ag1.getExperienciaPuntos());
System.out.println ("Esto ocurre porque a través de la copia hemos modificado el objeto, aunque luego la copia se pierda los cambios al objeto permanecen");
}
public static void probarAsignar(Agente agX) {
Agente ag3 = new Agente("id3", 66);
agX=ag3;
}
public static void probarModificar(Agente agX) {
agX.setExperienciaPuntos(99);
}
}
El resultado es: Ahora el agente1 tiene puntos: 33
Ahora el agente2 tiene puntos: 44
Pasamos al agente 1 como parámetro a probarAsignar y lo modificamos
Ahora el agente1 tiene puntos: 33
Esto ocurre porque lo que se pasa es una copia de la referencia
Pasamos al agente 1 como parámetro a probarModificar y lo modificamos
Ahora el agente1 tiene puntos: 99
Esto ocurre porque a través de la copia hemos modificado el objeto, aunque luego la copia se pierda los cambios al objeto permanecen
Esto también parece coherente: el método usa como parámetro una copia local de la referencia. Las modificaciones a la referencia no permanecen porque la copia se destruye posteriormente. En cambio, si usamos la referencia para manipular el objeto, dichos cambios sí permanecen porque a través de la copia hemos accedido a modificar el objeto en sí.
Un poco lioso pero creo que de momento no han surgido inconsistencias...
Saludos