Esta es una pregunta clásica de Java. Se han hecho muchas preguntas similares sobre stackoverflow y hay muchas respuestas incorrectas / incompletas. La pregunta es simple si no piensas demasiado. Pero podría ser muy confuso si lo piensa más.
1. Un fragmento de código interesante y confuso
public static void main(String[] args) { String x = new String("ab"); change(x); System.out.println(x); } public static void change(String x) { x = "cd"; } |
Imprime «ab».
En C ++, el código es el siguiente:
void change(string &x) { x = "cd"; } int main(){ string x = "ab"; change(x); cout << x << endl; } |
imprime «cd».
2. Preguntas frecuentes confusas
X almacena la referencia que apunta a la cadena «ab» en el montón. Así que cuando X se pasa como un parámetro al cambio() método, todavía apunta al «ab» en el montón como el siguiente:
Como java se pasa por valor, el valor de X es la referencia a «ab». Cuando el metodo cambio() se invoca, crea un nuevo objeto «cd» y X ahora apunta a «cd» como el siguiente:
Parece una explicación bastante razonable. Tienen claro que Java siempre se pasa por valor. Pero, ¿qué pasa aquí?
3. ¿Qué hace realmente el código?
La explicación anterior tiene varios errores. Para entender esto fácilmente, es una buena idea recorrer brevemente todo el proceso.
Cuando se crea la cadena «ab», Java asigna la cantidad de memoria necesaria para almacenar el objeto de cadena. Luego, el objeto se asigna a la variable X, a la variable se le asigna realmente una referencia al objeto. Esta referencia es la dirección de la ubicación de la memoria donde se almacena el objeto.
La variable X contiene una referencia al objeto de cadena. X ¡no es una referencia en sí misma! Es una variable que almacena una referencia (dirección de memoria).
Java es SÓLO paso por valor. Cuando se pasa x al método change (), se pasa una copia del valor de x (una referencia). El método cambio() crea otro objeto «cd» y tiene una referencia diferente. Es la variable x la que cambia su referencia (a «cd»), no la referencia en sí.
El siguiente diagrama muestra lo que realmente hace.
4. La explicación incorrecta
El problema que surge del primer fragmento de código no está relacionado con la inmutabilidad de las cadenas. Incluso si String se reemplaza con StringBuilder, el resultado sigue siendo el mismo. El punto clave es que la variable almacena la referencia, ¡pero no es la referencia en sí misma!
5. Solución a este problema
Si realmente necesitamos cambiar el valor del objeto. En primer lugar, el objeto debe ser modificable, por ejemplo, StringBuilder. En segundo lugar, debemos asegurarnos de que no haya ningún objeto nuevo creado y asignado a la variable de parámetro, porque Java solo se pasa por valor.
public static void main(String[] args) { StringBuilder x = new StringBuilder("ab"); change(x); System.out.println(x); } public static void change(StringBuilder x) { x.delete(0, 2).append("cd"); } |

