En Java, ¿los argumentos se pasan por valor o por referencia?

Escrito por picodotdev el .
java planeta-codigo
Enlace permanente Comentarios

En el lenguaje de programación Java los punteros no existen de la misma forma que en otros lenguajes como C o C++. En Java existen los punteros o referencias pero no son libres de apuntar a cualquier dirección de memoria del programa, en C y C++ lenguajes más destinados a la programación de sistemas y cercanos al lenguaje de la máquina ofrecen manipulación de punteros pudiendo obtener un puntero con la dirección de memoria de una variable.

En el lenguaje Java los punteros realmente son vistos simplemente como variables, no es posible obtener un puntero a la dirección de memoria de una variable, únicamente permite copiar o duplicar el valor de una variable en otra variable. Otra diferencia está en que en Java los argumentos de los métodos siempre se pasan por valor, en C y C++ los argumentos se pueden pasar por valor o por referencia.

Estas diferencias de Java con los lenguajes C y C++, hacen de Java un lenguaje más sencillo en la sintaxis, seguro y menos propenso a errores, por otro lado, la manipulación de punteros en C y C++ es útil en la programación de sistemas por ser un modelo similar al empleado por la CPU en su funcionamiento.

El paso por valor de los argumentos en Java

En Java todos los argumentos se pasan por valor. El paso por valor de los argumentos de un método en Java tiene varias consecuencias. El paso por valor significa que al método en la variable del argumento le llega una copia del valor en el caso de un tipo primitivo de datos o una copia del puntero a la dirección de memoria del objeto. En el paso por referencia el argumento contiene un puntero con la dirección de memoria de la variable. En el paso por valor al asignar un valor a la variable del argumento no modifica el valor de la variable usada para invocar al método, esto ocurre tanto para argumentos de tipo primitivo y para objetos.

Paso de argumentos por referencia y paso por valor

La palabra reservada final en los argumentos sirve para impedir asignar un nuevo valor a una variable, una variable final es una variable cuyo valor es una constante ya que en caso de intentar asignar a la variable un nuevo valor el compilador produce un error de compilación. La variable no pude cambiar de valor, sin embargo, si la variable es una referencia a un objeto el objeto si puede cambiar de estado, para que un objeto no pueda cambiar ha de ser inmutable.

Algunas clases como la clase String en Java son inmutables, esto significa que al manipular el objeto se devuelve una nueva instancia de la clase en vez de modificar la original. En Java para manipular un String y obtener la misma referencia en vez de una nueva instancia hay que utilizar la clase StringBufffer o StringBuilder. Algunas instancias de listas obtenidas con la API de colecciones son inmutables como List.of, y sus métodos add y remove lanzan la excepción en caso de ser invocados.

Ejemplo práctico del paso por valor

En este programa aunque a las variables de los argumentos x, y y w se les asigne un nuevo valor las variables a, b y c usadas en la invocación del método continúan teniendo el mismo valor. Las variables de los argumentos se pasan por valor, sin embargo, los objetos a los que apuntan esas variables si son mutables y son modificados en el método los cambios son visibles en el ámbito de invocación con la variable utilizada como argumento.

La lista de la variable d es modificada por el método, se corresponde con la variable z, y esos cambios son visibles en el ámbito de d, al contrario de las otras variables que aunque se les asigna un nuevo valor en el método fuera de él conservan su valor original aún después de la invocación del método. Esto ocurre porque en el caso de d se ha modificado el objeto mutable al cual tanto d y z apuntan.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

     public static void method(int x, String y, List<String> w, List<String> z) {
         x = 999;
         y = "Hola Mundo!";
         w = List.of("Hola", "mundo", "!");
         z.addAll(List.of("Hola", "mundo", "!"));
    }

    public static void main(String[] args) {
        int a = 1;
        String b = "Hello World!";
        List<String> c = Arrays.asList("Hello", "World", "!");
        List<String> d = new ArrayList(List.of("Hello", "World", "!"));
        
        Main.method(a, b, c, d);
        
        System.out.println("a: " + a);
        System.out.println("b: " + b);
        System.out.println("c: " + c);
        System.out.println("d: " + d);
    }
}
Main.java
1
2
3
4
a: 1
b: Hello World!
c: [Hello, World, !]
d: [Hello, World, !, Hola, mundo, !]
System.out

Puedes probar en tu equipo el ejemplo ejecutando el siguiente comando:
java Main.java


Comparte el artículo: