パッケージ


今回はパッケージについてみていきます。

パッケージとは

wikipedia引用

Javaパッケージは名前空間の中にあるJavaクラスをまとめるメカニズムである。 Javaパッケージは、JARファイルと呼ばれる圧縮ファイルの中に保存することができ、クラス群を一つのグループとしてまとめた方が1つずつダウンロードするよりも高速化される。プログラマも一般に同じカテゴリに属しているクラスや類似した機能を提供するクラスをまとめたパッケージを使う。
階層構造を持たず、クラス名の衝突を避けるために存在する。またそのパッケージ内にあるクラスに対しては、package privateといった設定が可能であり、package privateなクラスはパッケージ外部のクラスからのアクセスが禁止され、カプセル化による情報隠蔽を実現できる。

Javaを開発しているとクラスやインターフェースを再利用したいときがあります。そのとき、例えばAさんが作ったクラスとBさんが作ったクラスを再利用したいのですが、クラス名が重なってしまいました。重複のたびにクラス名を修正していくのは結構手間です。そこでAさんが作ったクラスは「makeA」というパッケージに入れ、Bさんが作ったクラスは「makeB」のパッケージに入れておくと、クラスの重複が起こったときにどのパッケージのクラスを利用すると指定することができます。
外部に公開するときはなおさらクラス名の重複が起こりやすいです。外部公開のときは「ドメイン名を逆から書いたものをパッケージ名にする」などの暗黙の規則があるようですが、パッケージの目的の1つに「クラス名の衝突を避ける」ということがあります。
他にも同じカテゴリや類似した機能をパッケージとしてまとめることによりクラスやインターフェースを使いやすくなります。

パッケージの宣言

【makeA > PackageSample.java】

package makeA;
public class PackageSample {
	public void show(){
		 System.out.println("makeAパッケージです。");
	}
}

【makeB > PackageSample.java】

package makeB;
public class PackageSample {
	public void show(){
		 System.out.println("makeBパッケージです。");
	}
}

2つの「PackageSample」という名前のクラスを作成します。通常ならクラス名の重複はエラーになりますが、パッケージを別にすることで同じクラス名でも作成することができます。

package パッケージ名;

どのパッケージに属するかは、ソースファイルの先頭に「package」キーワードで宣言します。パッケージを宣言しない場合はデフォルト・パッケージに属します。サンプルでは「makeA」と「makeB」という別のパッケージに属性しているのでクラス名の重複があってもエラーになりません。

パッケージの参照

【Sample.java】

public class Sample{
    public static void main(String[] args) {
    	makeA.PackageSample makeA_Obj = new makeA.PackageSample();
    	makeB.PackageSample makeB_Obj = new makeB.PackageSample();
    	makeA_Obj.show();
    	makeB_Obj.show();
    }
}
makeAパッケージです。
makeBパッケージです。

パッケージ名.クラス名 ○○ = new パッケージ名.クラス名();

パッケージのクラスを参照するには、クラス名の前に「パッケージ名+ドット」をつけます。どのパッケージに属するどのクラスと指定するわけです。呼び出し元と呼び出し先が同じパッケージに属しているならば、「パッケージ名+ドット」は省略できます。

単純名と限定名

import makeA.PackageSample;
public class Sample{
    public static void main(String[] args) {
    	makeA.PackageSample Obj1 = new makeA.PackageSample();
    	PackageSample Obj2 = new PackageSample();
    	Obj1.show();
    	Obj2.show();
    }
}
makeAパッケージです。
makeAパッケージです。

単純名とは「単一の識別子のみで構成される名前」のことです。簡単に言えば「パッケージ名+ドット」がなくクラス名だけで記述するのが単純名で、「パッケージ名+ドット」付きで書くのが限定名です。
呼び出し元と呼び出し先が同じパッケージに属しているならば、「パッケージ名+ドット」は省略できました。呼び出し元で呼び出し先をインポートすることで同様なことができます。

import パッケージ名.*;
import パッケージ名.クラス名;

クラスをインポートするには、importキーワードを使います。「パッケージ名・クラス名」で特定のクラスのみをインポートすることができますし、「パッケージ名・*」 とアスタリスクで指定するとそのパッケージに属する全てのクラスがインポートされます。

 import makeA.PackageSample;

1行目でmakeAパッケージのPackageSampleクラスをインポートしました。これでデフォルトパッケージに属するSampleクラスからでも「パッケージ名+ドット」のない単純名で参照することができます。

makeA.PackageSample Obj1 = new makeA.PackageSample();
PackageSample Obj2 = new PackageSample();

4行目は限定名でインスタンスを生成していますが、5行目は単純名でインスタンスを生成しています。同じクラスなのでメソッドの結果も当然同じです。

同名クラスをインポート

import makeA.PackageSample;
import makeB.PackageSample;
public class Sample{
    public static void main(String[] args) {
    }
}

パッケージmakeAのPackageSampleクラスとパッケージBのPackageSampleクラスをインポートしてみます。結果はエラーになります。同名のクラスを指定してインポートできません。

import makeA.*;
import makeB.*;
public class Sample{
    public static void main(String[] args) {
    	PackageSample Obj = new PackageSample();
    }
}

Exception in thread "main" java.lang.Error: Unresolved compilation problem
型 PackageSample はあいまいです

アスタリスクを使ってパッケージ全体をインポートすると、クラス名が重なってもエラーにならずにインポートできます。しかしクラスを参照するときは単純名ではできません。単純名ではどのパッケージのクラスなのかわからない為、一意になるように限定名で参照します。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です