Rareza en matrices Java comparadas: referencias frente a punteros
Tiene un problema para entender lo que está pasando en el siguiente código. El comportamiento de las matrices.c
yd
Es lo que yo esperaría. Pero que pasa cona
yb
? (También probé esto con variables normales, escalares, y no sucede nada sorprendente en ninguno de los casos).
La salida se copia a los comentarios RH.
import java.util.Arrays;
public class ArraysParadox {
public static void main(String[] args) {
int[] c = {1, 2, 3};
int[] d = {6, 5, 4, 3};
System.out.print("c: ");
System.out.println(Arrays.toString(c)); // c: [1, 2, 3]
System.out.print("d: ");
System.out.println(Arrays.toString(d)); // d: [6, 5, 4, 3]
System.out.println("--- swap ---");
int[] tmp = c;
c = d;
d = tmp; // <----- Magic?
System.out.print("c' (=d): ");
System.out.println(Arrays.toString(c)); // c' (=d): [6, 5, 4, 3]
System.out.print("d' (=c): ");
System.out.println(Arrays.toString(d)); // d' (=c): [1, 2, 3]
System.out.println("--- c = 0 ---");
Arrays.fill(c, 0);
System.out.print("c (=0): ");
System.out.println(Arrays.toString(c)); // c (=0): [0, 0, 0, 0]
System.out.print("d (=c): ");
System.out.println(Arrays.toString(d)); // d (=c): [1, 2, 3]
System.out.println("--- d = 1 ---");
Arrays.fill(d, 1);
System.out.print("c (=d): ");
System.out.println(Arrays.toString(c)); // c (=d): [0, 0, 0, 0]
System.out.print("d (=1): ");
System.out.println(Arrays.toString(d)); // d (=1): [1, 1, 1]
System.out.println("================");
int[] a = {1, 2, 3};
int[] b = {6, 5, 4, 3};
System.out.print("a: ");
System.out.println(Arrays.toString(a)); // a: [1, 2, 3]
System.out.print("b: ");
System.out.println(Arrays.toString(b)); // b: [6, 5, 4, 3]
a = b;
System.out.print("a (=b): ");
System.out.println(Arrays.toString(a)); // a (=b): [6, 5, 4, 3]
System.out.println("--- α = 0 ---");
Arrays.fill(a, 0);
System.out.print("a (=0): ");
System.out.println(Arrays.toString(a)); // a (=0): [0, 0, 0, 0]
System.out.print("b (=a?): ");
System.out.println(Arrays.toString(b)); // b (=a?): [0, 0, 0, 0] ???
System.out.println("--- b = 1 ---");
Arrays.fill(b, 1);
System.out.print("b (=1): ");
System.out.println(Arrays.toString(b)); // b (=1): [1, 1, 1, 1]
System.out.print("a (=b?): ");
System.out.println(Arrays.toString(a)); // a (=b?): [1, 1, 1, 1]
}
}
La intercambiabilidad dec
yd
indica paso por valor de acuerdo a este post:Java es pasar por valor, maldita sea!. (También miré¿La matriz java pasa por referencia no funciona?, pero no puedo entender el inglés del autor de la pregunta, y la llamada al método oscurece el ejemplo.)
Note que con la línead = tmp;
Comentado,c
yd
exhiben el mismo comportamiento extraño quea
yb
. Todavía no sé qué hacer con eso.
¿Alguien puede explicar cómoa
yb
¿Se puede explicar el comportamiento con paso por valor?
Resulta que el problema principal en mi publicación no es el paso por valor, sino el aliasing. Para dejar en claro la distinción entre paso por valor y punteros, agregué el siguiente método a mi código y lo usé para (intentar) intercambiarc
yd
(sugerido por unartículo enlazado por el artículo de JavaDude enlazado arriba).
static <T> void swap (T c, T d) {
T tmp = c;
c = d;
d = tmp;
}
El resultado es quec
yd
volver sin cambios Esto hubiera funcionado si Java (como C) pasara los punteros ac
yd
al método, pero en su lugar simplemente pasa sus valores, dejando las variables originales sin cambios.
Cambiandoa = b
aa = b.clone();
o paraa = Arrays.copyOf(b, b.length);
Da el comportamiento que estaba esperando. Este código también funciona:
int[] tmp = new int[b.length];
System.arraycopy( b, 0, tmp, 0, b.length );
a = tmp;
Momento relativo descritoaquí.