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 undbkann das Verhalten mit pass-by-value erklärt werden?

Edit: Nachtrag

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.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage