第7章 ファイル分割について
7.3 パッケージの利用について
それでは、パッケージの扱い方を、以下の2つのパターンから覚えていきましょう。
- 同じパッケージ内にあるクラスを、別のクラスから利用する。
- 異なるパッケージ内にあるクラスを、別のパッケージ内のクラスから利用する。
図 7.3.1: 同じパッケージ内にあるクラスを、別のクラスから利用する
図 7.3.2: 異なるパッケージ内にあるクラスを、別のパッケージ内のクラスから利用する
前者は7.1節のプログラムで既に行っていますが、復習を兼ねて次項のプログラムを紹介します。
7.3.1 同じパッケージ内のクラスにアクセスするプログラム
同一パッケージ内にあるクラスを、別のクラスから呼び出して動作するか確認します。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_1
③ 名前: Computer2
ソースコード① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_1
③ 名前: SamePackage
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
以下の2つのファイルを「jp.co.f1.basic.ch07_1」というパッケージに含め作成します。
なお、プログラムはmainメソッドのあるクラスが実行クラスになります。ソースコードが複数に別れるプログラムの場合は、mainメソッドのあるクラスを実行して下さい。
package jp.co.f1.basic.ch07_1; //Computer2クラスをパッケージに含める class Computer2 { private String os; private int memory; public void show() { System.out.println("OSは「" + this.os + "」です。"); System.out.println("メモリサイズは「" + this.memory + "MByte」です。"); } public void setOsMemory(String os, int memory) { // 引数の値をフィールド変数に設定 this.os = os; this.memory = memory; } }SamePackage.java
package jp.co.f1.basic.ch07_1; // SamePackageクラスをパッケージに含める public class SamePackage { public static void main(String[] args) { Computer2 com = new Computer2(); // Computer2クラスをオブジェクト化 com.setOsMemory("Windows7", 2048); // OSとメモリの値を設定 com.show(); // コンピュータの情報を確認 } }実行結果
Eclipse上でのファイル構成 解説
Eclipse上でのファイル構成から確認できるように「jp.co.f1.basic.ch07_1」パッケージ内に2つのファイル「Computer2.java」と「SamePackage.java」を作成し配置しています。
クラス単位でファイル分割しても、これまで学習してきたようにSamePackage.javaのmainメソッドから「Computer2クラスをオブジェクト化」して各メソッドを利用できます。
public static void main(String[] args) { Computer2 com = new Computer2(); //Computer2クラスをオブジェクト化 com.setOsMemory("Windows7", 2048); //OSとメモリの値を設定 com.show(); //コンピュータの情報を確認 }
図 7.3.3: 同じパッケージ内にあるクラスを、別のクラスから利用する
次に異なるパッケージ内のクラスを利用する方法について紹介します。
7.3.2 異なるパッケージ内のクラスを利用する(完全限定名による参照)
同じパッケージ内の別クラスを利用する方法については前項で学習しました。しかし異なるパッケージ内のクラスを利用する場合、単純にクラスファイルを別々のパッケージに分けても、別パッケージのクラスから利用できません。同じパッケージ内のクラスを利用する場合とは異なり、以下の2つの手順が必要になります。
① 利用されるクラスの先頭にはpublic修飾子をつける。
② 利用するクラス内では、利用されるクラス名にパッケージ名をつけて指定する。(完全限定名による参照)
書式:利用されるクラスの先頭にpublicをつける
書式:利用するクラスの中では、利用されるクラスにパッケージ名をつけて指定する
凡例:異なるパッケージ内のクラスの完全限定名を指定して呼び出す
パッケージ名を指定してクラスをインスタンス化することで、sample1パッケージ内のComputer1クラスを利用することができます。もちろん使用される側のアクセス修飾子が、「public」になっていることが前提になりますので合わせて覚えてください。
では次の項で、別パッケージからクラスを呼び出して使用するプログラムを紹介します。
7.3.3 異なるパッケージ内のクラスにアクセスするプログラム
異なるパッケージ内にあるクラスを、別パッケージのクラスから呼び出し動作することを確認します。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_2
③ 名前: Computer3
ソースコード① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_3
③ 名前: DifferentPackage1
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
以下のファイルを「jp.co.f1.basic.ch07_2」というパッケージに含め作成します。
Computer3.java※ファイル名(クラス名)とアクセス修飾子が違うだけで、内容はComputer2javaと同じです。
package jp.co.f1.basic.ch07_2; //Computer3クラスをパッケージに含めます public class Computer3 { // Computer3クラスを他から利用できるようにpublicをつけています private String os; private int memory; public void show() { System.out.println("OSは「" + this.os + "」です。"); System.out.println("メモリサイズは「" + this.memory + "MByte」です。"); } public void setOsMemory(String os, int memory) { // 引数の値をフィールド変数に設定 this.os = os; this.memory = memory; } }
以下のファイルを「jp.co.f1.basic.ch07_3」というパッケージに含め作成します。
DifferentPackage1.java※呼び出すクラスとインスタンス化の方法が違うだけで、内容はPackageSample02.javaと同じです。
package jp.co.f1.basic.ch07_3; // DifferentPackage1クラスをパッケージに含めます public class DifferentPackage1 { public static void main(String[] args) { // 別パッケージのComputer3クラスを完全限定名で指定してオブジェクト化 jp.co.f1.basic.ch07_2.Computer3 com = new jp.co.f1.basic.ch07_2.Computer3(); com.setOsMemory("WindowsXP", 1024); com.show(); } }実行結果
Eclipse上でのファイル構成
解説
まず「package jp.co.f1.basic.ch07_2」パッケージの「Computer3」クラスの3行目に、アクセス修飾子「public」がついています。これによりどこからでもアクセスし利用できるようになっています。
package jp.co.f1.basic.ch07_2; //Computer3クラスをパッケージに含めます public class Computer3 { //Computer3クラスを他から利用できるようにpublicをつけています
続いてjp.co.f1.basic.ch07_3パッケージのDifferentPackage1クラスのmainメソッド内から、パッケージ名をつけてComputer3クラスのオブジェクト化を行っています。
このパッケージ名をつけて完全限定名で指定を行うことで、Computer3クラスがある場所を示しています。
jp.co.f1.basic.ch07_2.Computer3 com = new jp.co.f1.basic.ch07_2.Computer3();
6行目でクラスのオブジェクト化さえ正しく行われれば、7、8行目のようにこれまで学習してきた方法で各メンバにアクセスして各処理を行うことができます。
com.setOsMemory("WindowsXP", 1024); //OSとメモリの値を設定 com.show(); //コンピュータの情報を確認
ポイント
- 別パッケージのクラスを利用する場合は「パッケージ名.クラス名」と完全限定名で指定する。
別パッケージのクラスを利用する際に、本項で学習した手順を行わなかったたらどうなるか実際に見てみましょう。
7.3.4 異なるパッケージ内のpublic修飾子がないクラスにアクセスするプログラム
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_2
③ 名前: Computer4
ソースコード① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_3
③ 名前: DifferentPackage2
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
以下のファイルを「jp.co.f1.basic.ch07_2」というパッケージに含め作成します。
Computer4.java※ファイル名(クラス名)とクラスのアクセス修飾子が違うだけで、内容はComputer3.javaと同じです。
package jp.co.f1.basic.ch07_2; //Computer4クラスをパッケージに含める class Computer4 { // アクセス修飾子publicをつけない private String os; private int memory; public void show() { System.out.println("OSは「" + this.os + "」です。"); System.out.println("メモリサイズは「" + this.memory + "MByte」です。"); } public void setOsMemory(String os, int memory) { // 引数の値をフィールド変数に設定 this.os = os; this.memory = memory; } }
以下のファイルを「jp.co.f1.basic.ch07_3」というパッケージに含め作成します。
DifferentPackage2.javapackage jp.co.f1.basic.ch07_3; public class DifferentPackage2 { public static void main(String[] args) { // 別パッケージのComputer4クラスを完全限定名で指定してオブジェクト化 jp.co.f1.basic.ch07_2.Computer4 com = new jp.co.f1.basic.ch07_2.Computer4(); com.setOsMemory("WindowsXP", 1024); // OSとメモリの値を設定 com.show(); // コンピュータの情報を確認 } }実行結果
利用される側のクラスにpublic修飾子がついていない為、コンパイルエラーになり実行できません。
アクセス修飾子がついていないクラスにアクセスできるのは、同一パッケージ内のクラスのみになり別パッケージ内のクラスからはアクセスできません。この仕組みを忘れている場合は、3章のアクセス修飾子を復習して下さい。※コンパイルエラー確認後は、DifferentPackage2クラスの6~8行目をコメントアウトして下さい。
今回は「jp.co.f1.basic.ch07_2」パッケージに「Computer4クラス」、「package jp.co.f1.basic.ch07_3」パッケージに「DifferentPackage2クラス」を含めました。Eclipse上でのファイル構成を確認しても分かるように、コンパイルエラーになっていることが確認できます。
これは利用される側のクラスComputer4クラスのアクセス修飾子に「public」がついていないことが原因です。
class Computer4 { //アクセス修飾子publicをつけない
アクセス修飾子publicがついていない場合は、異なるパッケージからアクセスできないようになっています。外部(他のパッケージ)からアクセスさせたい場合は必ず「public」をつけないといけません。
図 7.3.4: 異なるパッケージ内のクラスがアクセス修飾子により利用できない
次の項でもう1つ異なるパッケージの利用できないプログラムを紹介します。
7.3.5 異なるパッケージ内のクラスに完全限定名を使わずアクセスするプログラム
異なるパッケージ内のクラスを利用する際には、完全限定名で指定しないとアクセスできないことを確認します。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_2
③ 名前: Computer3
※7.3.3で作成したComputer3クラスを利用します。
① ソース・フォルダー: myproj_basic/src
② パッケージ: jp.co.f1.basic.ch07_3
③ 名前: DifferentPackage3
④ 作成するメソッド・スタブの選択:public static void main(String[] args) にチェックを入れる
ソースコード
Computer3.java
7.3.3で作成したComputer3クラスを利用します。
package jp.co.f1.basic.ch07_3; public class DifferentPackage3 { public static void main(String[] args) { //完全限定名なしでクラスをオブジェクト化 Computer3 com = new Computer3(); com.setOsMemory("WindowsXP", 1024); com.show(); } }実行結果
利用する側の記述に異なるパッケージ内のクラスを完全限定名で指定していない為、コンパイルエラーになり実行できない
※コンパイルエラー確認後は、DifferentPackage3クラスの6~8行目をコメントアウトして下さい。
今回は「package jp.co.f1.basic.ch07_3」パッケージに「DifferentPackage3クラス」を含めています。
Eclipse上でのファイル構成を確認しても分かるように、コンパイルエラーになっていることが確認できます。結論から言うとDifferentPackage3クラスの7行目で完全限定名を指定せずに「jp.co.f1.basic.ch07_2」パッケージの「Computer3」クラスを利用しようとしたためです。
Computer3 com = new Computer3();
完全限定名でクラスを指定しない場合、自身のファイル内もしくは同一パッケージ内にComputer3クラスを探します。今回のpackage jp.co.f1.basic.ch07_3パッケージ内にはComputer3クラスは無い為コンパイルエラーになってしまいます。完全限定名で指定しないと異なるパッケージのクラスをわざわざ探しには行ってくれません。
図 7.3.5: 異なるパッケージのクラスを利用する場合、完全限定名を指定しないと呼び出せない
今回のプログラムでは完全限定名を指定しなかったので、異なるパッケージのクラスを呼び出すことができませんでした。しかしJavaの仕組みにはいちいち完全限定名を書かなくても異なるパッケージのクラスを利用する仕組みが備わっています。その仕組みを「インポート」といい、次の節で詳しく説明を行っていきます。