第9章 クラスライブラリについて
9.3 クラス型の変数について
クラスライブラリについて学習したところで、この節からは「クラス型の変数」の仕組みについて学習していくことにします。これまでの学習で以下のようにオブジェクトを作成してきました。
comのようにオブジェクトを指す変数のことをクラス型の変数またはオブジェクト変数と呼びます。第2章で学習した参照型について思い出して下さい。クラス型の変数は型がクラスであり、その変数内にはオブジェクトの場所情報を保持しています。
クラス型の変数は、オブジェクトを作成する場合でなくても、基本データ型のようにいつでも「代入」を行うことができます。もちろん代入するデータは同じクラス型(オブジェクトの場所情報)である必要があります。
凡例のようにcom2変数にcom1の情報を代入することができます。代入ができる仕組みは基本データ型と変わりません。但し基本データ型とは違いオブジェクト内のデータコピーにならないことに気をつける必要があります。
ポイント
- クラス型変数(参照型変数)も基本データ型の変数ように代入を行うことができる。
それでは次の項でクラス型変数の代入を行うと、どのようになるのかプログラムを用いて説明していきます。
9.3.1 クラス型の変数に代入を行うプログラム
クラス型の変数にオブジェクトを指すクラス型の変数を代入し、それぞれのオブジェクトデータの確認を行います。クラス変数に別のクラス変数を代入した場合、どのような動きをするか学習しましょう。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch09
③ 名前: Computer1
ソースコード① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch09
③ 名前: AssignValueOfClassType1
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
Computer1.java
package jp.co.f1.basic.ch09; public class Computer1 { private String os; private int memory; // コンストラクタ public Computer1() { this.os = ""; this.memory = 0; System.out.println("パソコンを作成しました。"); } public void setComputer(String os, int memory) { this.os = os; this.memory = memory; System.out.println("OS「" + os + "」メモリサイズ「" + memory + "MByte」に設定しました。"); } public void show() { System.out.println("パソコンのOSは「" + os + "」です。"); System.out.println("メモリサイズは「" + memory + "MByte」です。"); } }
AssignValueOfClassType1.java
package jp.co.f1.basic.ch09; public class AssignValueOfClassType1 { public static void main(String[] args) { // クラス型変数com1を宣言し、Computer1オブジェクトを生成 System.out.println("com1を宣言しました。"); Computer1 com1 = new Computer1(); // OSとメモリ情報を設定 com1.setComputer("WindowXP", 1024); // クラス型変数com2を宣言 System.out.println("com2を宣言しました。"); Computer1 com2; // com2にcom1を代入 System.out.println("com2にcom1を代入しました。"); com2 = com1; System.out.println("\n-[情報変更前のPC情報表示]-------------"); System.out.print("com1の"); // com1の情報を表示 com1.show(); System.out.println(); System.out.print("com2の"); // com2の情報を表示 com2.show(); System.out.println("--------------------------------------\n"); } }実行結果
解説
AssignValueOfClassType1クラスの5行目から10行目はこれまで学習してきた内容になっています。
7行目でnew演算子を用いてComputer1クラスをインスタンス化し、クラス型変数のcom1に代入しています。そして9行目ではインスタンスメソッドのsetComputerメソッドを利用し各値を設定しています。
//クラス型変数com1を宣言し、Computer1オブジェクトを生成 System.out.println("com1を宣言しました。"); Computer1 com1 = new Computer1(); //OSとメモリ情報を設定 com1.setComputer("WindowXP", 1024);
続いて14行目ではComputer1型の変数com2を宣言のみを行っています。7行目の処理のようにクラス型変数にはnew演算子を用いて、必ずオブジェクトの代入を行わなければならないというルールはありません。
Computer1 com2;
18行目では14行目で用意したcom2にcom1を代入しています。
com2 = com1;
22行目でcom1からインスタンスメソッドのshowメソッドを呼び出し、25行目もcom2からインスタンスメソッドのshowメソッドを呼び出して画面にパソコン情報を表示しています。
com1.show(); … com2.show();
実行結果から分かるように当然com1は情報が予想通り表示されています。com1を代入されたcom2もcom1と同様の情報を表示します。つまりcom1とcom2のオブジェクト変数は同じ実体を指していることになります。
クラス型の変数に同じクラス型の変数が代入できることは学習できました。実行結果を見ると同じ情報が出力されていることが確認できます。まるで同じ「コンピュータ」オブジェクトが2つ存在するように見えます。しかし、実際にはオブジェクトが2つになっている訳ではありません。ここで思い出して欲しいのですが、クラス型の変数の中にはオブジェクトの場所情報が格納されています。
クラス型の変数は「Computerオブジェクト」をそっくりコピーするのはなく、この「オブジェクトの場所情報」がコピーされて代入されます。
図 9.3.1: クラス型変数の代入
では実際に同じオブジェクトを参照していることを、次のプログラムで確認していきます。
9.3.2 同じオブジェクトを参照している2つの変数の内容を確認するプログラム
同じオブジェクトをさしている(参照している)2つのクラス変数を用意し、一方のクラス変数を使用し、オブジェクトの値を変更したら別のオブジェクト値も変更されるかを確認します。複数のクラス変数で参照しているオブジェクトの値を変更した場合、どのような動きをするか学習しましょう。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch09
③ 名前: Computer1
ソースコード① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch09
③ 名前: AssignValueOfClassType2
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
Computer1.java
※9.3.1で作成したComputer1クラスを利用します。
AssignValueOfClassType2.java
※9.3.1のAssignValueOfClassType1.javaの内容に28~38行の処理を追加したソースコードです。
package jp.co.f1.basic.ch09; public class AssignValueOfClassType2 { public static void main(String[] args) { // クラス型変数com1を宣言し、Computer1オブジェクトを生成 System.out.println("com1を宣言しました。"); Computer1 com1 = new Computer1(); // OSとメモリ情報を設定 com1.setComputer("WindowXP", 1024); // クラス型変数com2を宣言 System.out.println("com2を宣言しました。"); Computer1 com2; // com2にcom1を代入 System.out.println("com2にcom1を代入しました。"); com2 = com1; System.out.println("\n-[情報変更前のPC情報表示]-------------"); System.out.print("com1の"); // com1の情報を表示 com1.show(); System.out.println(); System.out.print("com2の"); // com2の情報を表示 com2.show(); System.out.println("--------------------------------------\n"); // com1から変更を行う System.out.println("com1のコンピュータに変更を加えました。"); com1.setComputer("Windows7", 4096); System.out.println("\n-[情報変更後のPC情報表示]-------------"); System.out.print("com1の"); // com1の情報を表示 com1.show(); System.out.println(); System.out.print("com2の"); // com2の情報を表示 com2.show(); System.out.println("--------------------------------------"); } }実行結果
解説
26行目までの処理は9.3.1で紹介したサンプルと同じです。
30行目の処理でcom1からインスタンスメソッドのsetComputerメソッドを呼び出し、値の変更を行っています。
//com1から変更を行う System.out.println("com1のコンピュータに変更を加えました。"); com1.setComputer("Windows7", 4096);
34行と37行目で再度com1、com2からインスタンスメソッドのshowメソッドを呼び出して、PC情報を画面に出力しています。実行結果から分かるように、com1からしか変更処理を行っていないのにも関わらずcom2の出力結果もcom1と同様の結果を出力しています。
com1.show(); … com2.show();
図 9.3.2: オブジェクト内容の変更
上記図が示すように「変数com1とcom2は異なる2つのオブジェクトではなく、同じ1つのオブジェクトを指している」ことになります。クラス型の変数に代入を行うということは、「代入された側の変数が、代入した側の変数と同じオブジェクトを指すようになる」ということを意味します。
基本データ型の代入は値のコピーを行いますが、クラス型の変数は参照先のコピーになるという仕組み必ず覚えておいて下さい。
ポイント
- クラス変数の代入を行うことで、1つのオブジェクトを2つ以上の変数で指し示すことがある。