参照データ型は、変数に実態を持たないため、代入では参照値が引き渡されます。これを十分理解していないと思わぬトラブルに巻き込まれます。
この資料では、参照型での代入の仕組みと注意点を見てみましょう。
基本データ型と参照データ型についておさらいしてみましょう。
基本データ型は変数自体にデータの値を保持していますが、参照データ型の変数には、データの値ではなく、データのある場所を保持しています。この、データのある場所のことを参照値といいます。
前記したように、参照データ型の変数は、値の実態が格納されている場所を持ちます。
そこで、参照データ型の代入を想像してみてください。代入式 「 A = B ; 」は、B 変数の内容を A 変数に設定しますが、ここで B 変数 の何が A 変数に設定されるのでしょうか? 参照データ型の代入では、実態が代入されることは無く、実態の場所である、参照値が代入されます。つまり 「 A = B ; 」 を実行した後の B 変数と A 変数は、同じ参照値を持つことなり、1つの実態を両者が参照することになるわけです。
実は、ここに初心者が陥りやすい問題が隠れています。
上記のように代入された場合でも、実態は一つなので、どちらか一方の値を変更したつもりでが、もう一方の変数の値も変更されるといった事態になります。
次のコードは、「int型」の変数に 2 つ対して、一方の変数の値をもう一方の変数の値に代入した後、代入もとの変数の値を書き換えるという内容です。
public class test { public static void main(String[] args) { int i1 = 10; int i2 = i1; i1 = 20; System.out.println("i1 = "+i1+" i2 = "+i2); } }
このコードの実行結果は次のように、変数の値はそれぞれ異なる値になります。当たり前といえば、当たり前のことですね。
i1 = 20 i2 = 10
前のコードは、「int型」の変数を使用しました。そこで、「int型」の変数を自分で作成した「数値を保持するクラス」に置き換えてみたいと思います。
まずは、数値を保持するクラス「Num」を作成します。このクラスでは、「int型」の値を保持します。
public class Num { private int num; public Num(int num){ this.num = num; } public void setNum(int num){ this.num = num; } public int getNum(){ return this.num; } }
それでは、基本データ型の実行例と同じように、作成したクラスを使用して同じことをしてみましょう。
public class test { public static void main(String[] args) { Num i1 = new Num(10); Num i2 = i1; i1.setNum(20); System.out.println("i1 = "+i1.getNum()+" i2 = "+i2.getNum()); } }
実行結果は以下のようになります。 代入先の変数である「i2」については、値を変更するコードは書いていないにもかかわらず、値が変化してしまうのがわかります。
i1 = 20 i2 = 20
データ型 ( Okapi 版 Java リファレンス )