以下のコードで何が起こっているのかを理解するのに問題があります。配列の振る舞いc
とd
は私が期待するものです。しかし、何が起こっているのa
でしょb
うか?(これも通常のスカラー変数で試しましたが、どちらの場合も驚くべきことは何も起こりません。)
出力は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]
}
}
この投稿によると、とのスワップ可能性は値渡しc
をd
示します。Javaは値渡しです、くそっ!。( Java配列の参照渡しも機能しませんか?を調べましたが、質問者の英語が理解できず、メソッド呼び出しによって例がわかりにくくなっています。)
d = tmp;
行がコメントアウトされており、c
およびとd
同じ奇妙な動作を示していることに注意してa
くださいb
。それでもどうしたらいいのかわからない。
誰もがどのようa
にそしてb
の振る舞いを値渡しで説明できるかを説明できますか?
編集:補遺
私の投稿の主な問題は、値渡しではなく、エイリアシングであることがわかりました。値渡しとポインターの違いを明確にするために、次のメソッドをコードに追加し、それを使用してスワップc
と(上記のリンクされたJavaDudeの記事によってリンクされた記事d
によって提案された)スワップを実行しました。
static <T> void swap (T c, T d) {
T tmp = c;
c = d;
d = tmp;
}
結果はそれでc
あり、d
変更されずに戻ってきます。これは、Java(Cなど)がメソッドへのポインターc
とd
メソッドへのポインターを渡す場合に機能しますが、代わりに、元の変数を変更せずに値を渡すだけです。
に変更a = b
するa = b.clone();
か、に変更するとa = Arrays.copyOf(b, b.length);
、期待していた動作が得られます。このコードも機能します:
int[] tmp = new int[b.length];
System.arraycopy( b, 0, tmp, 0, b.length );
a = tmp;
ここで説明する相対的なタイミング。