web-dev-qa-db-ja.com

メソッドの配列を変更すると、配列の外側が変更されます

変数のスコープに問題があります。

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でした。メソッドで配列の値を変更したのに、元の配列が変更されたのはなぜですか?

18
purblue

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番目の引数で指定されたサイズの)新しい配列オブジェクトが割り当てられ、既存の配列の内容がそこにコピーされ、その新しい配列への参照が返されます。

11
Brian Roach

定義:

  • 参照=配列が存在するメモリ内の場所を指す変数。
  • 参照の値=実際のメモリアドレスの場所自体

配列の参照の値をtest()メソッドに渡しました。 Javaは値渡しであるため、配列(つまり、コピー)の値ではなく、参照の値を渡します。

Cのバックグラウンドがある場合は、参照をポインタとして考える方が簡単な場合があります。したがって、参照の値は基本的にはメモリアドレスです(ここでは、Javaルールを曖昧にしていますが、このように考えるのが最も簡単かもしれません)。

したがって、例では、配列を指す参照の値をtest()メソッドに渡します。このメソッドは、その参照値を使用して、配列がメモリ内にある場所を検索し、データにアクセスできるようにしますあなたの配列で。

test()メソッドでは、配列の参照(ポイントする場所、つまり_test = new int[10];_)を変更しないため、test()メソッドは、配列(まだ元の配列の場所を指しているため)、要素_0_が_5_の値に設定されることになります。

1
SnakeDoc