Estranheza em matrizes de Java equacionadas: referências vs. ponteiros
Tendo um problema em entender o que está acontecendo no código abaixo. O comportamento de matrizesc
ed
é o que eu esperaria. Mas o que está acontecendo coma
eb
? (Eu também tentei isso com variáveis escalares normais, e nada de surpreendente acontece em ambos os casos.)
A saída é copiada para os comentários do 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]
}
}
A possibilidade de troca dec
ed
indica pass-by-value de acordo com este post:Java é pass-by-value, droga!. (Eu também olhei parapassagem de matriz java por referência não funciona?, mas não consigo entender o inglês do solicitante e a chamada do método obscurece o exemplo.)
Observe que com a linhad = tmp;
comentado,c
ed
exibir o mesmo comportamento estranho comoa
eb
. Ainda não sei o que fazer com isso.
Alguém pode explicar comoa
eb
O comportamento de uma pessoa pode ser explicado com valor de passagem?
Acontece que o principal problema no meu post não é passar por valor, mas aliasing. Para ser claro sobre a distinção entre pass-by-value e ponteiros, adicionei o seguinte método ao meu código e usei-o para (tentar) trocarc
ed
(sugerido por umartigo vinculado pelo artigo de JavaDude vinculado acima).
static <T> void swap (T c, T d) {
T tmp = c;
c = d;
d = tmp;
}
O resultado é quec
ed
Volte inalterado. Isso teria funcionado se Java (como C) passasse por ponteiros parac
ed
para o método, mas simplesmente passa seus valores, deixando as variáveis originais inalteradas.
Mudandoa = b
paraa = b.clone();
ou paraa = Arrays.copyOf(b, b.length);
dá o comportamento que eu estava esperando. Este código também funciona:
int[] tmp = new int[b.length];
System.arraycopy( b, 0, tmp, 0, b.length );
a = tmp;
Tempo relativo descriedAqui.