5-1:パッケージとモジュールの管理

Javaのモジュールの管理のルールとパッケージとの関係を解説します。


・ Javaでは、開発されたモジュール(アプリケーションの部品)は 非常に簡潔なルールによって管理されています。

Javaのクラス管理の階層
バイトコードコンパイル単位パッケージ クラスライブラリ
単独のクラス同一のソースファイル パッケージ名が共通階層構造を持つパッケージ

もちろん、1つのクラスのみを含むコンパイル単位、 単独のコンパイル単位のみのパッケージ、 サブ・パッケージを含まないクラスライブラリが存在してもかまいません。

・ ソースファイル内でパッケージ名を指定しない場合は、 暗黙のうちに「名前なしのパッケージ」という共通のパッケージに 含まれると解釈されます。 アプリケーションの規模が小さい場合は、これで特に問題ありません。 ただし大規模な開発を行う場合は、クラス名の衝突を防ぐためにもパッケージ名 の指定が必要になってきます。 パッケージの定義を行うべきでしょう。 パッケージの指定は、各ソースファイルの先頭で package文を用いて パッケージ名を宣言するだけです。 (package文はコメント文を除いて、他のすべての記述より先に位置しなくては いけません。) パッケージを定義した場合の開発環境については、 次の2点を理解することがポイントとなります。

  1. パッケージと作業ディレクトリの対応
  2. 環境変数 CLASSPATH

 各クラスがバイトコードというファイルに対応するように、 各サブ・パッケージの階層構造は、現実のファイルシステムのディレクトリ構造に 対応させるルールになっています。 したがってパッケージの宣言を行った場合には、 package文で宣言されたパッケージ名と同じ名前のディレクトリを作成しておき、 その内部で作業を行う必要があります。 サブパッケージが宣言される場合には、 ディレクトリの階層構造を含めて同一の名前にしておきます。 たとえば、あるソースファイルの先頭で、 次のようなパッケージ文の宣言を含むクラス定義があったとしましょう。


package mygame.network;
public class Message {
         :
         :

上の宣言の意味は「クラス Messageが、 パッケージ mygame の中のサブパッケージ networkに所属すること」を 意味します。このソースプログラム内に定義されたクラスのバイトコードは、 最終的に必ずディレクトリ mygameの下のディレクトリ networkの中に置かれなくては いけません。(通常はソースファイルも同じディレクトリに置くのが普通でしょう。)


-(CLASSPATH)-+- mygame -+- network -+- Message.java
                                    +- Message.class


 さて、上のディレクトリ名は相対指定になっていることに気付いたと思います。 パッケージ名に対応するディレクトリの出発点はどこにすればいいのでしょうか? それを決めるのが CLASSPATH と呼ばれる環境変数です。 クラスライブラリにアクセスするには、 その「ルート・ディレクトリ」に該当する場所を「クラスパス」として指定します。 CLASSPATHには出発点のディレクトリは複数指定することが可能です。 環境変数の設定法方はシステムの環境に多少依存します。 たとえばカレントディレクトリと /usr/java/libディレクトリの2つを CLASSPATHに指定したい場合を考えてみましょう。 Solarisの Kシェルなど UNIXの Bシェル系の環境、 UNIXの Cシェル系の環境、Windowsの MS-DOSウィンドウの場合、それぞれ 次のようになります。


CLASSPATH=.:/usr/java/lib ; export CLASSPATH    # Bシェル

setenv CLASSPATH .:/usr/java/lib                # Cシェル

set CLASSPATH=.;/usr/java/lib                   # MS-DOS

実際にアプリケーションを開発している最中には、 アプリケーションのパッケージの「出発点」を 絶対パス名で CLASSPATHの中に含めておくようにしておくべきでしょう。 コンパイルやプログラムの実行の際に、パッケージ名も含めて識別が必要だからです。 その場合には、コンパイルの作業はそれぞれのパッケージに対応するディレクトリの 中で普通の方法で行えます。 もし、CLASSPATHの値がデフォルトの「カレントディレクトリのみ」の場合には、 上の mytool.network.Messageのコンパイルを実行するために、 親ディレクトリの中で次のように指定することになります。


javac  mygame/network/Message.java     #UNIXの場合

javac  mygame\network\Message.java     #MS-DOSの場合

javacコマンドが引数に指定するのは、現実のパス名を含むソースファイル名です。 (実際に作業しているディレクトリの場所に依存する。 パスの区切り記号もシステムに依存。) これに対して、 javaコマンドが引数に指定するのは CLASSPATHを起点としたパッケージ名を 含むクラス名です。(作業しているディレクトリの場所には依存しない。) 実行するためには必ず CLASSPATHの中にパッケージの出発点のディレクトリが 含まれていなくてはなりません。そして実行の方法は次のように パッケージ名を .(ピリオド)で区切って指定します。


java  mygame.network.Message