配列変数と配列本体
配列変数の代入
配列変数を他の配列変数に代入することができます。 配列変数の代入は、配列本体のコピーと勘違いされがちですが、その本当の意味を説明したいと思います。
では早速、サンプルプログラムArraySample05を見てください。
ArraySample05.java
class ArraySample05 { public static void main(String[] args) { int[] a = {1, 2, 3, 4, 5}; int[] b = {6, 7, 8, 9}; System.out.print("aが指す配列本体は"); for(int i = 0; i < a.length; i++) System.out.printf(" %2d", a[i]); System.out.println(); System.out.print("bが指す配列本体は"); for(int i = 0; i < b.length; i++) System.out.printf(" %2d", b[i]); System.out.println(); b = a; System.out.println("aをbに代入しました。"); b[0] = 10; System.out.println("b[0]に10を代入しました。"); System.out.print("aが指す配列本体は"); for(int i = 0; i < a.length; i++) System.out.printf(" %2d", a[i]); System.out.println(); System.out.print("bが指す配列本体は"); for(int i = 0; i < b.length; i++) System.out.printf(" %2d", b[i]); System.out.println(); } }
配列a, bの内容が最終的にどのようになっているかを予想してから、ArraySample05を実行してみてください。
それでは、実行結果をスクリーンショットで見てみましょう。
いかかでしょう。予想は当たりましたか。 ArraySample05では、まず
int[] a = {1, 2, 3, 4, 5}; int[] b = {6, 7, 8, 9};
と配列a, bを初期化しています。そして
b = a;
b[0] = 10;
のように、aをbに代入してからb[0]に10を代入しています。 したがって、配列aは{1, 2, 3, 4, 5}のままで、配列bだけが{10, 2, 3, 4, 5}になると予想されたかもしれません。 しかし、結果はaとbの両方とも{10, 2, 3, 4, 5}となっています。
aをbに代入しても、aが参照する配列本体と同じ内容のコピーが作られ、bがそのコピーを参照するようになるわけではないのです。 実際には、aの参照先がbに代入されます。 つまり、aが参照している配列本体をbも参照するようになるだけなのです。 従って、aをbに代入した後でb[0]に10を代入すると、a[0]も10になってしまいます。 この様子を表すのが図 8-7です。
配列変数を別の配列変数に代入しても、配列本体のコピーにはならない。
配列本体のコピー
それでは、配列本体をコピーするためにはどうすればいいのでしょうか。 何のことはありません。 コピー元の配列本体と同じ長さの新しい配列本体を生成して、for文等を使って、各要素を一つずつコピーしていくだけのことです。
ArraySample06は、配列aを配列bにコピーするプログラムです。
ArraySample06.java
class ArraySample06 { public static void main(String[] args) { int[] a = {1, 2, 3, 4, 5}; int[] b = {6, 7, 8, 9}; System.out.print("aが指す配列本体は"); for(int i = 0; i < a.length; i++) System.out.printf(" %2d", a[i]); System.out.println(); System.out.print("bが指す配列本体は"); for(int i = 0; i < b.length; i++) System.out.printf(" %2d", b[i]); System.out.println(); b = new int[a.length]; //配列bの配列本体を生成し直す。 for(int i = 0; i < a.length; i++) //配列aの各要素を配列bへコピーする。 b[i] = a[i]; System.out.println("配列aを配列bにコピーしました。"); b[0] = 10; System.out.println("b[0]に10を代入しました。"); System.out.print("aが指す配列本体は"); for(int i = 0; i < a.length; i++) System.out.printf(" %2d", a[i]); System.out.println(); System.out.print("bが指す配列本体は"); for(int i = 0; i < b.length; i++) System.out.printf(" %2d", b[i]); System.out.println(); } }
ArraySample06の実行結果は次のようになります。
ArraySample06でも、ArraySample05同様、配列a, bをそれぞれ初期化しています。
int[] a = {1, 2, 3, 4, 5}; int[] b = {6, 7, 8, 9};
そして、次の部分では、まず配列aと同じ長さの配列本体を生成して、その参照をbに代入しています。 続くfor文では、配列aの各要素を、同じインデックスを持つ配列bの要素に代入していきます。
b = new int[a.length]; //配列bの配列本体を生成し直す。 for(int i = 0; i < a.length; i++) //配列aの各要素を配列bへコピーする。 b[i] = a[i];
この段階で、配列aから配列bへのコピーは完了しています。 したがって、ここで
b[0] = 10;
が実行されると、b[0]だけが10となり、a[0]は1のままとなります。
この流れを図 8-9にまとめておきます。
配列本体をコピーするためには、コピー元の配列本体と同じ長さの配列本体を生成してから、各要素を一つ一つコピーしていく。
ArraySample05やArraySample06では、配列本体{6, 7, 8, 9}が、どの配列変数からも参照されなくなってしまいました。 この後、この配列本体はどうなってしまうのでしょうか。 これについては次の節で詳しく解説します。