Solución:
Todo en Java se pasa por valor. En el caso de una matriz (que no es más que un Objeto), la referencia de la matriz se pasa por valor (al igual que una referencia de objeto se pasa por valor).
Cuando pasa una matriz a otro método, en realidad se copia la referencia a esa matriz.
- Cualquier cambio en el contenido de la matriz a través de esa referencia afectará la matriz original.
- Pero cambiar la referencia para que apunte a una nueva matriz no cambiará la referencia existente en el método original.
Vea esta publicación: ¿Java es “paso por referencia” o “paso por valor”?
Vea este ejemplo de trabajo:
public static void changeContent(int[] arr) {
// If we change the content of arr.
arr[0] = 10; // Will change the content of array in main()
}
public static void changeRef(int[] arr) {
// If we change the reference
arr = new int[2]; // Will not change the array in main()
arr[0] = 15;
}
public static void main(String[] args) {
int [] arr = new int[2];
arr[0] = 4;
arr[1] = 5;
changeContent(arr);
System.out.println(arr[0]); // Will print 10..
changeRef(arr);
System.out.println(arr[0]); // Will still print 10..
// Change the reference doesn't reflect change here..
}
Tu pregunta se basa en una premisa falsa.
Las matrices no son un tipo primitivo en Java, pero tampoco son objetos … “
De hecho, todas las matrices en Java están objetos1. Cada tipo de matriz de Java tiene java.lang.Object
como supertipo, y hereda la implementación de todos los métodos en el Object
API.
… entonces, ¿se pasan por valor o por referencia? ¿Depende de lo que contenga la matriz, por ejemplo, referencias o un tipo primitivo?
Respuestas breves: 1) pasar por valor y 2) no hay diferencia.
Respuesta más larga:
Como todos los objetos Java, las matrices se pasan por valor … pero el valor es la referencia a la matriz. Entonces, cuando asigna algo a una celda de la matriz en el método llamado, estará asignando al mismo objeto de matriz que ve la persona que llama.
Esto NO es paso por referencia. Verdadero pasar por referencia implica pasar el dirección de una variable. Con verdadero pass-by-reference, el método llamado puede asignar a su variable local, y esto hace que se actualice la variable en el llamador.
Pero no en Java. En Java, el método llamado puede actualizar el contenido de la matriz y puede actualizar su copia de la referencia de la matriz, pero no puede actualizar la variable en el llamador que contiene la referencia de la matriz del llamador. Por lo tanto … lo que proporciona Java NO es pasar por referencia.
Aquí hay algunos enlaces que explican la diferencia entre paso por referencia y paso por valor. Si no comprende mis explicaciones anteriores, o si se siente inclinado a no estar de acuerdo con la terminología, deberían leerlos.
- http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
- http://www.cs.fsu.edu/~myers/c++/notes/references.html
Pregunta SO relacionada:
- ¿Java es “pasar por referencia” o “pasar por valor”?
Antecedentes históricos:
La frase “pasar por referencia” era originalmente “llamada por referencia”, y se usó para distinguir la semántica de paso de argumentos de FORTRAN (llamada por referencia) de la de ALGOL-60 (llamada por valor y llamada por nombre).
-
En la llamada por valor, la expresión del argumento se evalúa a un valor y ese valor se copia en el método llamado.
-
En la llamada por referencia, la expresión del argumento se evalúa parcialmente a un “lvalue” (es decir, la dirección de una variable o elemento de matriz) que se pasa al método de llamada. El método de llamada puede leer y actualizar directamente la variable / elemento.
-
En la llamada por nombre, la expresión del argumento real se pasa al método de llamada (!!) que puede evaluarlo varias veces (!!!). Esto fue complicado de implementar y podría usarse (abusado) para escribir código que era muy difícil de entender. La llamada por nombre solo se usó en Algol-60 (¡afortunadamente!).
ACTUALIZAR
En realidad, la llamada por nombre de Algol-60 es similar a pasar expresiones lambda como parámetros. El problema es que estas expresiones no-exactamente-lambda (se las denominaba “thunks” en el nivel de implementación) indirectamente modificar el estado de las variables que están dentro del alcance en el procedimiento / función de llamada. Eso es parte de lo que los hizo tan difíciles de entender. (Consulte la página de Wikipedia sobre el dispositivo de Jensen, por ejemplo).
1. Nada en las preguntas y respuestas vinculadas (matrices en Java y cómo se almacenan en la memoria) indica o implica que las matrices no son objetos.
Las matrices son de hecho objetos, por lo que se pasa una referencia (la referencia en sí misma se pasa por valor, ¿todavía está confundida?). Ejemplo rápido:
// assuming you allocated the list
public void addItem(Integer[] list, int item) {
list[1] = item;
}
Verá los cambios en la lista desde el código de llamada. Sin embargo, no puede cambiar la referencia en sí, ya que se pasa por valor:
// assuming you allocated the list
public void changeArray(Integer[] list) {
list = null;
}
Si pasa una lista no nula, no será nula cuando el método regrese.