lunes, 16 de marzo de 2015

Java y su paso de valor "Referenciado"

Hace un tiempo, en mi paso por #GEx, se presentó una duda razonable en cuanto a #java.

Si tu creas un objeto y lo pasas a una variable, que es lo que pasa?? Mi respuesta inmediata fue: se referencia, por lo cual no se reserva memoria para este paso.

supongamos que tenemos una clase Algo y un código así.

Algo a = new Algo();
Algo b = a;
a = null;

Y esto causo realmente la duda, si a es ahora nula, por que b no? Y es que aunque a y b estén referenciados al mismo objeto, no están relacionados de ninguna otra forma, por lo que una asignación como en este caso, al objeto a, lo desenganchará del objeto original, pero no afectara a b en lo mínimo. Por lo cual, a es nulo, pero b sigue apuntando al objeto original, pero no es realmente asi.

Si bien, la VM relaciona la variable a y b por medio del id, a y b son una copia del objeto creado (Si, al ser copia, se hace la asignación de este en memoria). Así que si hacemos algo como esto (disculpen que use la imprudencia de #Groovy, pero es que si soy un poco flojo).

class Algo{
  def name;
}

Algo a = new Algo(name:"basura")
Algo b = a

println "Esto contiene la variable a: ${a.getName()}"
println "Esto contiene la variable b: ${b.getName()}"
println "Este es el id del objeto a: ${a.hashCode()}"
println "Este es el id del Objeto b: ${b.hashCode()}"

En este punto, la variable name va a tener el mismo valor tanto para a como para b, y los id de cada uno serán idénticos, lo cual nos haría pensar que si, el paso es por referencia y no por valor. Y si seguimos jugando con esto, mas nos hará pensar lo mismo!

b.setName("Random");
println "Esto contiene la variable a: ${a.getName()}"
println "Esto contiene la variable b: ${b.getName()}"
println "Este es el id del objeto a: ${a.hashCode()}"
println "Este es el id del Objeto b: ${b.hashCode()}"
a.setName("Uetiko")
println "Esto contiene la variable a: ${a.getName()}"
println "Esto contiene la variable b: ${b.getName()}"
println "Este es el id del objeto a: ${a.hashCode()}"
println "Este es el id del Objeto b: ${b.hashCode()}"

Y si, sigue cambiando y cambiando y no deja de ser el mismo id, pero como bien se ha mencionado antes, todo cambia cuando haces a una de las dos nula:

a = null
try{
  println "Esto contiene la variable a: ${a.getName()}"
}catch(Exception e){
  println e.getMessage()
}
println "Esto contiene la variable b: ${b.getName()}"
println "Este es el id del Objeto b: ${b.hashCode()}"

Aquí vemos como la variable 'a' la hacemos nula y la marcamos para que sea procesada por el GC, y esperanzados a que b, que era una referencia, pues muera de igual forma, por desgracia no es así como funciona, ya que si recordamos las sabias palabras de Ken Arnold y James Gosling, nos damos cuenta que si, la VM al estar pensada para que corra en diferentes arquitecturas, lo mas lógico es que la única forma de pasar valores en java, es por valor, ya que esto ayuda a la simpleza.

Con amor, Random.

1 comentario: