Antes de describir como son pasados los argumentos en Java, es mejor entender como Java almacena las variables en memoria. Básicamente hablamos de dos tipos de variables: primitivas y objetos.

Las variables primitivas siempre son almacenadas en la memoria stack, sin embargo en el caso de los objetos estos son almacenados en dos etapas, los objetos actuales son almacenados en la memoria heap y la referencia a objetos se encuentra almacenada en la memoria stack que apunta a los objetos.

1. Por valor y Por referencia

Que significa “Por valor” y “Por referencia”.

  • Por valor: cuando los argumentos son pasados por valor a los métodos, significa que se realiza una copia de la variable y esta es enviada al método y no la original, entonces todo los cambios realizados dentro del método solo afectan a la copia actual.
  • Por referencia: cuando los argumentos son pasados por referencia, significa que la referencia o el puntero a la variable original son pasadas a los métodos y no la data original.

2. ¿Como son pasados los argumentos en Java?

En Java, los argumentos son siempre pasados por valor independientemente del tipo de variable. Cada que el método es invocado, pasa lo siguiente:

  • Una copia del argumento es pasado en la memoria stack y la copia es pasada en el método
    • Si la variable original es primitiva, es simple, una copia de la variable es creada en el stack y esta se pasa al método
    • Si la variable original no es primitiva, entonces una nueva referencia o apuntador es creado dentro de la memoria stack que apunta al objeto actual y la nueva referencia es pasada al método, (en esta etapa, 2 referencias apuntan al mismo objeto).

3. Revisando algunas preocupaciones

En el siguiente ejemplo, tratamos de validar “en java siempre se realiza el pase por valor” pasando un conjunto de tipos de argumentos (primitivas, tipos wrappers, colecciones, objetos de negocio) y observar como son modificados despues de la llamada al método.

3.1 Paso de argumentos primitivos:

Salida:

Descripción de la salida:

Las dos variables y y x son tipos primitivos y son almacenadas en la memoria stack. Cuando se llama a modifyPrimitiveTypes(), se realizan dos copias dentro de la memoria stack y luego estas son pasadas al método. Las variables originales no fueron enviadas al método y cualquier modificación dentro del método solo afectan a las copias.

3.2 Paso de argumentos tipo wrappers:

Salida:

Descripción de la salida:

Los tipos wrappers son almacenados en la memoria heap con la respectiva referencia en la memoria stack.

Cuando se llama a modifyWrappers(), una copia a dicha referencia es creada dentro de la memoria stack y las copias son pasadas a los métodos. Cualquier cambio en la referencia dentro del método modifica el valor de las referencias y no los valores originales.

Nota:

Si realiza un cambio de una variable del tipo wrapper dentro del método de la siguiente forma: x+=2, el cambio no se refleja fuera del método desde que los objetos wrapper son inmutables, lo que significa que se crea una nueva instancia cada que el estado es modificado. Los objetos String funcionan en forma similar a los objetos wrappers, aplican las mismas reglas.

3.3 Paso de colecciones como argumentos:

Salida:

Descripción de la salida:

Cuando se define un ArrayList o cualquier colección en Java, la referencia es creada dentro del stack y esta apunta a múltiples objetos que son almacenados en la memoria heap. Cuando se llama a modifyList(), una copia de la referencia es creada y se pasa al método, entonces el objeto actual tiene 2 referencias y cualquier cambio realizado a una referencia se refleja en la otra.

Dentro del método, llamamos a lstParam(2), que actualmente trata de crear un nuevo objeto Integer en la memoria heap y se enlaza a la lista actual de objetos. Por lo tanto la lista original puede ver las modificaciones desde que ambas referencias apuntan al mismo objeto en memoria.

3.4 Paso de objetos de negocios como argumentos

Salida:

Descripción de la salida:

El objeto student es creado dentro de la memoria heap y la referencia se encuentra en la memoria stack, cuando se llama a modifyStudent(), una copia de la referencia es creado dentro del stack y esta se pasa al método. Cualquier modificación dentro de los atributos del objetos dentro del método son reflejadas en la referencia original.

4. Conclusión

En Java, los argumentos son pasados por valor, la copia puede ser una referencia o una variable dependiendo del tipo original de la variable. Desde ahora, usted puede utilizar las siguientes recomendaciones a fin de entender como la modificación de argumentos dentro del método afectan a la variable original:

  1. La modificación de valores tipos primitivos, nunca afectan a la variable original
  2. Si se cambia la referencia al objeto dentro del método esto nunca afecta a la referencia original, sin embargo esto crea un nuevo objeto en la memoria heap.
  3. Modificar los atributos de un objeto pasado como argumento se refleja fuera del método.
  4. Modificar colecciones y maps siempre se reflejan fuera del método.

Este artículo se encuentra basado en Java – pass by reference or pass by value. Consideramos que es un concepto importante y que en realidad muy pocos conocen, pues por lo general no es tocado dentro de los cursos de programación.

Si les parece interesante o tienen un aporte adicional, por favor, dejen sus comentarios.

Java : paso de valores por referencia o por valor
Si te gusto, comparte ...Email this to someone
email
Share on Facebook
Facebook
Tweet about this on Twitter
Twitter
Share on LinkedIn
Linkedin
Share on Google+
Google+
Etiquetado en:    

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Facebook
A %d blogueros les gusta esto: