Dziwność w zrównanych tablicach Java: odniesienia do wskaźników
Masz problem ze zrozumieniem, co dzieje się w poniższym kodzie. Zachowanie tablicc
id
tego bym się spodziewał. Ale o co chodzia
ib
? (Próbowałem też tego z normalnymi, skalarnymi zmiennymi i nic dziwnego nie dzieje się w żadnym przypadku.)
Dane wyjściowe są kopiowane do komentarzy 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]
}
}
Możliwość wymianyc
id
wskazuje wartość przekazu według tego wpisu:Java jest warta swojej wartości, do diabła!. (Ja też spojrzałemjava tablica pass by reference nie działa?, ale nie mogę zrozumieć angielskiego języka pytającego, a wywołanie metody przesłania przykład.)
Zauważ, że z liniąd = tmp;
skomentował,c
id
wykazują takie samo dziwne zachowanie jaka
ib
. Nadal nie wiem, co z tym zrobić.
Czy ktoś może wyjaśnić, jaka
ib
zachowanie można wyjaśnić przez przekazywanie wartości?
Okazuje się, że głównym problemem w moim poście nie jest wartość pass-by-value, ale aliasing. Aby mieć jasność co do rozróżnienia między wartościami „pass-by-value” i wskaźnikami, dodałem następującą metodę do mojego kodu i użyłem go do (spróbowania) wymianyc
id
(sugerowane przezartykuł linkowane przez artykuł JavaDude'a powyżej).
static <T> void swap (T c, T d) {
T tmp = c;
c = d;
d = tmp;
}
Rezultat jest takic
id
wróć niezmieniony. To by działało, gdyby Java (jak C) przekazywała wskaźniki doc
id
do metody, ale zamiast tego po prostu przekazuje ich wartości, pozostawiając oryginalne zmienne bez zmian.
Wymiana pieniędzya = b
doa = b.clone();
luba = Arrays.copyOf(b, b.length);
daje zachowanie, którego się spodziewałem. Ten kod również działa:
int[] tmp = new int[b.length];
System.arraycopy( b, 0, tmp, 0, b.length );
a = tmp;
Określono czas względnytutaj.