Jose Dueñas

Soy desarrollador web freelance.
Convierto tus ideas en aplicaciones web potentes y atractivas. ¿Quieres contratarme?

Paso de variables por Valor y por Referencia en Java

< Publicidad >
En la programación, ya sea para aplicaciones simples como para websites como investools, siempre se encontrará una serie de retos y normas a tener en cuenta. Sino, echa un vistazo a la programación en Java de éste post.
< / Publicidad >

En el paso de parámetros de variables a métodos en Java se suele decir que:

  • las variables de tipo simple (int, double, etc) se pasan por valor
  • los objetos se pasan por referencia.

Ésto no es cierto, después de consultar varias fuentes puedo concluir que en Java las variables, ya sean simples u objetos, se pasan siempre por valor.

El hecho de hacernos pensar que los objetos se pasan por referencia se debe a que si pasamos un objeto a un método y modificamos su valor dentro del método, al salir de éste, nuestro objeto habrá sido modificado.
Pero nosotros en realidad no hemos pasado el objeto como tal, sino que hemos pasado por valor la referencia al objeto, es decir, le hemos pasado una copia de su dirección en memoria.

Por lo tanto, cuando pasamos un objeto a un metodo, siempre estaremos pasando una copia de su dirección, por lo que aunque le cambiemos la direccion, en cuanto salga del metodo, volverá a tener la dirección original. Sin embargo, si dentro del método accedemos a su contenido y lo modificamos, éste si que seguirá modificado una vez salgamos del método, porque el contenido no es ninguna copia.

Para que se entienda mejor, podéis probar ésto:

import java.awt.Point;
   class PassByValue
   {
     public static void modifyPoint(Point pt, int j)
     {
        pt.setLocation(5,5);                                      //1
        j = 15;
        System.out.println("During modifyPoint " + "pt = " + pt +
                           " and j = " + j);
     }
     public static void main(String args[])
     {
        Point p = new Point(0,0);                                 //2
        int i = 10;
        System.out.println("Before modifyPoint " + "p = " + p +
                           " and i = " + i);
        modifyPoint(p, i);                                        //3
        System.out.println("After modifyPoint " + "p = " + p +
                           " and i = " + i);

     }
   }
  

Que dará de salida esto:

Before modifyPoint p = java.awt.Point[x=0,y=0] and i = 10 During modifyPoint pt = java.awt.Point[x=5,y=5] and j = 15 After modifyPoint p = java.awt.Point[x=5,y=5] and i = 10


-->



Comentarios

  1. KURAGARi 23 Febrero

    Comment Arrow

    Y si lo que quieres es poder cambiar el contenido de un tipo básico como el bolean, el int o el String dentro de un método (lo que en C# se hace añadiendo un “ref” que preceda la declaración del parámetro o el & de C/C++) como lo harías?


  2. Jose Dueñas 23 Febrero

    Comment Arrow

    @KURAGARi: de una forma directa como en C no se puede ya que como dijimos Java siempre pasa por valor los tipos básicos.
    Una posible solución pasaría por “camuflar” ese tipo básico en un objeto.
    Por ejemplo, pasariamos como argumento un array que contendria solamente a éste tipo básico para poder modificarlo sin problema.
    Veámoslo con ujemeplo en el que cambiamos una variable de tipo int:

    public static void modificarVariable(int [] array)
    {
         array[0] = 99; //mi nuevo valor sera 99
    }
    
    public static void main(String args[])
    {
         int[] miVariable = { 1 };
         modificarVariable(miVariable);
         System.out.println("El nuevo valor de mi variable es: " + miVariable[0]);
    }

    De todos modos es poco elegante y se debería evitar ésta práctica.

    Un saludo


  3. Mariano 10 Marzo

    Comment Arrow

    Lo que dice KURAGARi no es posible debido a que Java, a diferencia de C*, no permite trabajar con punteros. Para hacer lo que tu dices es necesario poder manejar punteros a memoria


  4. Franco 22 Abril

    Comment Arrow

    Mas elegante seria instanciar una clase wrapper de integer, por ejemplo: Integer nro = new Integer(3);
    Y luego llamas al metodo y modificas su (estado) valor como quieras.


  5. Jose Dueñas 22 Abril

    Comment Arrow

    Hola Franco,
    efectivamente, pero se trataba de ver cómo hacerlo para variables de tipo simple, no objetos. Ya sabemos que los objetos se pasan siempre por referencia.


  6. Gonzalo 2 Julio

    Comment Arrow

    Sin embargo los tipos basicos encapuslados (Integer, Character, etc) no pueden modificar su valor, asi que tampoco vale pasar un Integer.
    Parece que el array es la mejor opcion, a fin de cuentas un array de un elemento no es mas que un puntero a ese elemento ;)


  7. robertito 19 Agosto

    Comment Arrow

    Buenas,
    me he encontrado con un pequeño problema referente a todo esto…. tengo un objeto y quiero crear otro igual, pero OTRO. si hago
    Objeto a = new Objeto();
    Objeto b = a;
    si modifico b, tambien se modifica a. como podria evitar esto? crear una copia de este objeto, y no crear otra referencia al mismo objeto?
    muchas gracias…


  8. Miguel Vegallero 17 Septiembre

    Comment Arrow

    Robertito, fácilmente:

    Objeto a = new Objeto(); // Se crea el objeto a
    .
    . // Se modifica el objeto a
    .
    Objeto b = new Objeto(a); // Se crea el objeto b, que es clon de a


  9. Juan 24 Octubre

    Comment Arrow

    Saludos Jose, mi duda es si dices que en java las variables simples u objetos se pasan simpre por valor, porque en tu segundo comentario dices “Ya sabemos que los objetos se pasan siempre por referencia.”. me podrias aclarar eso por favor. Gracias


  10. Jose Dueñas 25 Octubre

    Comment Arrow

    Hola Juan,
    si, en realidad quería decir que se pasa por valor la referencia al objeto (su dirección).


  11. CESARS 31 Octubre

    Comment Arrow

    Hola, tengo una pregunta, es que nececito cambiar una variable de tipo int a String, y despues de convertirla mostrarla en una textfield.
    asi voy en el momento.

    String dato,resultado;//variables
    int intdato,intresultado;//variables

    dato= textField.getString();//tomo el valor del texField
    intdato=Integer.parseInt(dato);//aqui cambio la variable string a entero
    intresultado = intdato*intdato; //aquie hago la operacion.

    pero no se como convertir la variable intresultado en una variable de tipo String y mostrarla en otro textField(1).


  12. Pat 26 Diciembre

    Comment Arrow

    Querido José,

    Gracias por el ejemplo que presentas; es muy claro e ilustra perfectamente la problemática descrita.

    Sin embargo, no estoy de acuerdo con la semántica que has utilizado. En tu artículo, dices:

    “(…) en Java las variables, ya sean simples u objetos, se pasan siempre por valor.”

    A mi parecer, esta frase puede llevar a error. En mi opinión, en los parámetros a funciones en Java:

    “Los objetos se pasan por referencia” -> Es decir, el objeto se pasa al método utilizando una referencia a él.

    “La referencia a un objeto se pasa por valor” -> Es decir, se realiza una copia de la referencia al objeto.

    Un saludo




Sobre el Autor

Jose Dueñas

Jose Dueñas es un Desarrollador Web Senior que actualmente trabaja para Soluciones Center SAL. Es un geek interesado por casi todo que disfruta escribiendo sobre tecnología y algunas otras cosas.