Verrücktheit in gleichgestellten Java-Arrays: Referenzen vs. Zeiger
Problem beim Verstehen der Vorgänge im folgenden Code. Das Verhalten von Arraysc
undd
ist das, was ich erwarten würde. Aber was ist los mita
undb
? (Ich habe dies auch mit normalen skalaren Variablen versucht, und in beiden Fällen passiert nichts Überraschendes.)
Die Ausgabe wird in die RH-Kommentare kopiert.
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]
}
}
Die Austauschbarkeit vonc
undd
gibt den Pass-by-Wert gemäß diesem Beitrag an:Java ist Pass-by-Value, verdammt!. Ich habe auch angeschautJava-Array als Referenz übergeben funktioniert nicht?, aber ich kann das Englisch des Fragestellers nicht verstehen, und der Methodenaufruf verdeckt das Beispiel.)
Beachten Sie das mit der Linied = tmp;
auskommentiert,c
undd
zeigen das seltsame Verhalten wiea
undb
. Ich weiß immer noch nicht, was ich davon halten soll.
Kann mir jemand erklären wiea
undb
kann das Verhalten mit pass-by-value erklärt werden?
Es stellt sich heraus, dass das Hauptproblem in meinem Beitrag nicht das Pass-by-Value, sondern das Aliasing ist. Um die Unterscheidung zwischen Pass-by-Value und Zeigern zu verdeutlichen, habe ich meinem Code die folgende Methode hinzugefügt und sie zum (Versuch-) Austauschen verwendetc
undd
(vorgeschlagen von einemArtikel verlinkt durch den oben verlinkten Artikel von JavaDude).
static <T> void swap (T c, T d) {
T tmp = c;
c = d;
d = tmp;
}
Das Ergebnis ist dasc
undd
Komme unverändert zurück. Dies hätte funktioniert, wenn Java (wie C) Zeiger an übergeben hättec
undd
Die Methode übergibt stattdessen einfach ihre Werte und lässt die ursprünglichen Variablen unverändert.
Änderna = b
zua = b.clone();
oder zua = Arrays.copyOf(b, b.length);
gibt das Verhalten, das ich erwartet hatte. Dieser Code funktioniert auch:
int[] tmp = new int[b.length];
System.arraycopy( b, 0, tmp, 0, b.length );
a = tmp;
Relatives Timing beschriebenHier.