変数のスコープに問題があります。
public static void main(String[] args){
int[] test={1,2,3};
test(test);
System.out.println(test[0]+" "+test[1]+" "+test[2]);
}
static void test(int[] test){
test[0]=5;
}
1 2 3
への出力を期待していましたが、結果は5 2 3
でした。メソッドで配列の値を変更したのに、元の配列が変更されたのはなぜですか?
Javaはオブジェクトです。new
を介して配列を作成すると、配列がヒープ上に作成され、参照値(Cのポインターに類似)が返されます。変数に割り当てられます。
Cでは、これは次のように表現されます。
_int *array = malloc(10 * sizeof(int));
_
その変数をメソッドに渡すと、メソッドのローカル(スタック)変数に割り当てられた(コピーされた)参照値が渡されます。配列の内容はコピーされず、参照値のみがコピーされます。この場合も、Cの関数へのポインタを渡すのと同じです。
したがって、その参照を介してメソッドの配列を変更すると、ヒープに存在する単一の配列オブジェクトが変更されます。
_int[] temp=test
_ ...を介して配列の「コピー」を作成したとコメントしましたが、これはメモリ内の単一の配列を指す参照値(ポインター)のコピーのみを作成します。これで、すべて同じ配列への同じ参照を保持する3つの変数があります(main()
に1つ、メソッドに2つ)。
配列の内容のコピーを作成する場合、Javaは Arrays
クラスの静的メソッド を提供します:
_int[] newArray = Arrays.copyOf(test, test.length);
_
これにより、ヒープに(2番目の引数で指定されたサイズの)新しい配列オブジェクトが割り当てられ、既存の配列の内容がそこにコピーされ、その新しい配列への参照が返されます。
定義:
配列の参照の値をtest()
メソッドに渡しました。 Javaは値渡しであるため、配列(つまり、コピー)の値ではなく、参照の値を渡します。
Cのバックグラウンドがある場合は、参照をポインタとして考える方が簡単な場合があります。したがって、参照の値は基本的にはメモリアドレスです(ここでは、Javaルールを曖昧にしていますが、このように考えるのが最も簡単かもしれません)。
したがって、例では、配列を指す参照の値をtest()
メソッドに渡します。このメソッドは、その参照値を使用して、配列がメモリ内にある場所を検索し、データにアクセスできるようにしますあなたの配列で。
test()
メソッドでは、配列の参照(ポイントする場所、つまり_test = new int[10];
_)を変更しないため、test()
メソッドは、配列(まだ元の配列の場所を指しているため)、要素_0
_が_5
_の値に設定されることになります。