En Java siempre se utiliza el mecanismo pass-by-value (paso por valor), pero hay una particularidad para los objetos:
Por lo tanto, los cambios en los campos del objeto dentro del método se reflejan en el objeto original, pero el intento de asignar una nueva referencia a la variable dentro del método no afecta al objeto original. Esto a menudo se confunde con pass-by-reference, ¡pero Java no soporta pass-by-reference!
Ejemplo:
void changePrimitive(int a) { a = 10; } void changeObject(Point p) { p.x = 10; } int num = 5; changePrimitive(num); // num sigue siendo 5 Point pt = new Point(1, 2); changeObject(pt); // ahora pt.x == 10
¡Importante! Si dentro del método se asigna p = new Point(100, 200), el objeto original fuera del método no cambiará. ¡Se cambia el campo del objeto, no su referencia!
Pregunta: ¿Se puede desde el método cambiar el objeto pasado como argumento, de tal manera que fuera del método la variable-referencia apunte a un nuevo objeto?
Respuesta: No, no se puede. Al asignar una nueva referencia al argumento dentro del método, esto solo afecta a la copia de la referencia, que se pierde al salir del método. Fuera del método, la variable-argumento apunta al objeto anterior.
void reassign(Point p) { p = new Point(100, 200); // ¡solo localmente! } Point pt = new Point(5, 5); reassign(pt); // pt sigue siendo (5, 5)
Historia
En un gran sistema financiero se implementó una API que "retornaba" cambios en el objeto, modificando la referencia dentro del método. Como resultado, después de salir del método, los cambios no se reflejaban. Se necesitó rediseñar completamente parte de la lógica para delimitar claramente la mutación y el retorno de nuevos objetos.
Historia
Al intentar implementar un swap para dos objetos en Java con el método
swap(A a, B b), el desarrollador pasaba referencias y las intercambiaba dentro del método. Esto no funcionó. Era necesario devolver el resultado o utilizar contenedores-arreglos. El desconocimiento del pass-by-value llevó a un intercambio incorrecto de objetos.
Historia
Uno de los participantes del proyecto migró la lógica desde C++ y esperaba el comportamiento de pass-by-reference. Como resultado, los métodos dejaron de funcionar correctamente: los cambios dentro del método no "salían" al exterior. Se necesitó reescribir urgentemente partes críticas del código, lo que llevó un tiempo considerable.