配列の変数同士の代入
9.5 配列の変数同士の代入
変数同様、配列変数を別の配列変数に代入することもできます。但し、変数と違い、配列の値そのものがコピーされるわけではなく、配列変数の参照先(値のある住所のようなもの)がコピーされます。
基本データ型(byte, short, int, long, float, double, char, boolean)の変数には、実際の値が入っています。しかし、配列変数は基本データ型と異なり、実際の値がある場所を参照するための情報が入っています。
参照先がコピーされるとはどういうことなのでしょうか。
神田マンションA棟には、居住年数3年、2年、4年の住民がそれぞれの部屋に住んでいたとします。この度、神田マンションA棟のリフォーム工事のため、神田マンションB棟に移ってもらうことにしました。住民のデータを、神田マンションB棟のデータを管理する配列でも使えるようにします。
図 9.5.1 : 配列変数に別の配列変数を代入する前のイメージ
int型の配列である変数kandaMansionAは、3つの要素を持っています。
int型の配列である変数kandaMansionBにkandaMansionAを代入すると、kandaMansionAが参照していた要素を見に行くのです。それによって、図 9.5.2で示すように3つの要素は共有されることになります。
図 9.5.2 : 2つの配列変数は3つの要素をもつ同じ実体を参照(共有)している
9.5.1 配列変数へ配列変数の代入を使ったプログラム
プログラムを作成し、配列の変数が別の変数へ代入され、要素が共有されることを確認してみましょう。
① ソース・フォルダー :myproj_intro/src
② パッケージ :jp.co.f1.intro.ch9
③ 名前 :ChangeArrayElement2
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
➢ ChangeArrayElement2.java
package jp.co.f1.intro.ch9; public class ChangeArrayElement2 { public static void main(String[] args) { // 飲み物の価格を管理する配列kandaPriceの宣言と要素を初期化 int[] kandaPrice = { 100, 200, 300 }; // 飲み物の価格を管理する配列akibaPriceを宣言し配列kandaPriceで初期化 int[] akibaPrice = kandaPrice; System.out.println("--- 神田店 --- "); System.out.println("お茶 :" + kandaPrice[0] + "円"); System.out.println("紅茶 :" + kandaPrice[1] + "円"); System.out.println("コーヒー:" + kandaPrice[2] + "円"); System.out.println("-- 秋葉原店 -- "); System.out.println("お茶 :" + akibaPrice[0] + "円"); System.out.println("紅茶 :" + akibaPrice[1] + "円"); System.out.println("コーヒー:" + akibaPrice[2] + "円"); System.out.println(); System.out.println("※価格改定後"); // 秋葉店の紅茶の価格を変更 akibaPrice[1] = 240; System.out.println("--- 神田店 --- "); System.out.println("お茶 :" + kandaPrice[0] + "円"); System.out.println("紅茶 :" + kandaPrice[1] + "円"); System.out.println("コーヒー:" + kandaPrice[2] + "円"); System.out.println("-- 秋葉原店 -- "); System.out.println("お茶 :" + akibaPrice[0] + "円"); System.out.println("紅茶 :" + akibaPrice[1] + "円"); System.out.println("コーヒー:" + akibaPrice[2] + "円"); } }
実行結果
解説
int型の配列変数kandaPriceを宣言し、3つの要素の記憶領域を確保すると同時に任意の値で初期化します。
図 9.5.3 : 配列の作成と要素の初期化
int型の配列変数akibaPriceを宣言し、int型の配列変数kandaPriceを代入します。図 9.5.がそのイメージ図になります。配列変数に配列変数を代入するということは、要素の場所を表す住所情報をコピーし、同じ要素を参照していると言えます。
図 9.5.4 : 配列変数に別の配列変数を代入
13~21行目で、それぞれの配列変数が参照する要素の値を表示し、確認しています。
13~21行目の実行結果は以下のようになります。配列変数kandaPriceと配列変数akibaPriceは同じ要素を参照しているので、同じインデックスの要素には同じ値が入っています。
次に、27行目で配列変数akibaPriceのインデックス1の要素に異なる値を代入します。このイメージは次の図 9.5.5になります。
図 9.5.5 : 同じ要素を参照する配列変数の要素に値を代入
30~32行目、35~37行目では、配列変数の要素の値を表示します。27行目の実行後に要素の値にどのような変化があったのかを確認できます。
29~37行目の実行結果は下の図のようになりました。配列変数akibaPriceも配列変数kandaPriceも同じ要素を参照しているので、配列変数kandaPriceのインデックス1の値も同じ値に変わりました。
9.5.2 配列の要素を共有せずにコピーする方法
配列の要素の値を共有せず、コピーする方法もあります。それには、下の書式のように、要素のインデックスを指定する必要があります。
この場合は、要素は共有されずに独立しているので、片方の配列が同じインデックスにある要素の値を変更しても、もう一方の配列の同じインデックスの要素に影響が及ぶことはありません。
図 9.5.6 : 配列の要素の値の代入(コピー)
9.5.3 配列の要素に別の配列の要素を代入するプログラム
配列の要素に別の配列の要素を代入して表示するサンプルプログラムを作成し、結果を確認します。
このソースコードは、先ほどのChangeArrayElement2.javaの内容の一部を変更したものです。
① ソース・フォルダー :myproj_intro/src
② パッケージ :jp.co.f1.intro.ch9
③ 名前 :ChangeArrayElement3
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
➢ ChangeArrayElement3.java
package jp.co.f1.intro.ch9; public class ChangeArrayElement3 { public static void main(String[] args) { // 飲み物の価格を管理する配列kandaPriceの宣言と要素を初期化 int[] kandaPrice = { 100, 200, 300 }; // 飲み物の価格を管理する配列akibaPriceを宣言し配列kandaPriceの各要素で初期化 int[] akibaPrice = new int[3]; akibaPrice[0] = kandaPrice[0]; akibaPrice[1] = kandaPrice[1]; akibaPrice[2] = kandaPrice[2]; System.out.println("--- 神田店 --- "); System.out.println("お茶 :" + kandaPrice[0] + "円"); System.out.println("紅茶 :" + kandaPrice[1] + "円"); System.out.println("コーヒー:" + kandaPrice[2] + "円"); System.out.println("-- 秋葉原店 -- "); System.out.println("お茶 :" + akibaPrice[0] + "円"); System.out.println("紅茶 :" + akibaPrice[1] + "円"); System.out.println("コーヒー:" + akibaPrice[2] + "円"); System.out.println(); System.out.println("※価格改定後"); // 秋葉原店の紅茶の価格を変更 akibaPrice[1] = 240; System.out.println("--- 神田店 --- "); System.out.println("お茶 :" + kandaPrice[0] + "円"); System.out.println("紅茶 :" + kandaPrice[1] + "円"); System.out.println("コーヒー:" + kandaPrice[2] + "円"); System.out.println("-- 秋葉原店 -- "); System.out.println("お茶 :" + akibaPrice[0] + "円"); System.out.println("紅茶 :" + akibaPrice[1] + "円"); System.out.println("コーヒー:" + akibaPrice[2] + "円"); } }
実行結果
解説
8行目でint型の配列変数kandaPriceを宣言し、3つの要素の記憶領域を確保し、それぞれを任意の値で初期化します。
図 9.5.7 : 配列変数の宣言と同時に要素の記憶領域確保と初期化
11行目ではint型の配列変数akibaPriceを宣言し、new演算子で新しくint型の要素の記憶領域を3つ確保します。それぞれの要素にはint型の規定値0で初期化されます。
図 9.5.8 : 配列変数の宣言と要素の記憶領域確保
int型の配列変数akibaPriceの要素にint型の配列変数kandaPriceの要素を代入します。このイメージは次の図 9.5.9になります。配列変数に配列変数を代入するのと異なるのは、値のある場所の参照ではなく、値を受け渡している点です。
図 9.5.9 : 配列の要素に別の配列の要素の値を代入(コピー)
17~19行目と22~24行目で、それぞれの要素に代入されている値を画面に表示し確認します。
配列変数に配列変数を代入した時は、どちらかの配列変数の要素の値を変更すると、もう片方の配列変数の同じインデックスの要素の値も変更されてしまいました。それは、同じ要素を参照していたからです。
今回のプログラムでは、それぞれが別々の場所にある要素を参照しているので、片方の配列変数の要素の値を変更しても、もう片方に影響が出ません。
30行目でint型の配列変数akibaPriceのインデックス1の要素に240を代入します。
図 9.5.10 : 要素に値を代入
33~35行目と38~40行目で変更後の値を表示させます。
32~40行目の実行結果は次のようになりました。配列変数akibaPriceのインデックス1の要素のみ値が変わっているのを確認して下さい。
ポイント・ 配列変数に別の配列変数を代入すると、それぞれは同じ実体を参照(共有)する。
・ 配列の要素の値をコピーするには、対象のインデックスで指定する。