戻る

パッケージ

   パッケージは、関連のあるクラス、あるいはインターフェースを集めたもので、1つの名前空間を作るものである。
  名前空間というのは名前(クラス名やフィールド、メソッド名など)に有効範囲を設定するものである。

   これから新しいパッケージを作成し、それをファイルとして利用するまでの手順を見ていく。その流れは、次のようになる。

   パッケージの作成
    ↓
   パッケージに含まれるクラスファイルをディレクトリに配置
    ↓
   パッケージに含まれるクラスファイルを使う

package文

   パッケージを作成するには、package文を使う。

   package パッケージ名;

   例えば、次はpack1というパッケージを作成する事を示す。

   package pack1;

   paackage文は、そのソースファイルにあるクラスがこのパッケージに入る事を示す。

   (あるソースファイル)
   package pack1; ・・・・・package文はソースファイルの先頭に置く

   class A { ・・・・・・・・・・このクラスはパッケージpack1に所属
     …
   }
   class B { ・・・・・・・・・・このクラスもパッケージpack1に所属
     …
   }

   package文は、そのソースファイルの最初の文にしなければならない。ただし、その前にコメントを置く事は構わない。

   次にPackというパッケージを作るソースファイルを示す。このソースファイルには、Pack_1というクラスが含まれている。

   サンプル:Pack_1.java

   //
   //Pack_1.java---Packというパッケージの作成
   //
   package Pack;

   //このパッケージに含まれるクラス
   public class Pack_1 {
    public void show( ) {
     System.out.println("Pack_1: show");
    }
   }

   次にこのPack_1.javaをコンパイルした所を示す。

   $ javac Pack_1.java
   $ dir -1
   -rw-r--r-- 1 kt   users   398 Mar 11 21:32 Pack_1.class
   -rw-r--r-- 1 kt   users   206 Mar 11 21:31 Pack_1.java

   Pack_1.javaといえども、普通のjavaのソースファイルに過ぎない。
  コンパイルすれば、クラスファイルが作られる。この例では、Pack_1.classというクラスファイルが作られている。

クラスファイルの配置

   パッケージを「ファイルシステムの中のどこに置くか」は色々な方法があるが、ここでは次の方法を説明する。

   ・ パッケージと同名のディレクトリを作成する
   ・ そこにクラスファイルをファイルする
   ・ import文で使用するパッケージを指定する
   ・ 必要なら環境変数CLASSPATHに検索するディレクトトリの起点を登録する

   この手順に従い、前項で作成したパッケージPackを利用する方法を見ていく。
   まず、パッケージと同名の;ディレクトリを作成する。この場合、パッケージ名がPackなので、Packとうディレクトリを作成する。
  作成する場所はどこでもよい。(あとで、その場所を環境変数CLASSPATHで指定する。)
  ここでは、カレントディレクトリの下にそのディレクトリを作成する事にする。

   $ mkdir Pack ・・・・・ディレクトリPackを作成
   $ dir -dl Pack ・・・・確認
   drwxr-xr-x  2 kt   users   1024 Mar 11 23:01 Pack/
   $ _

   次にこのディレクトリにクラスファイルを配置する。

   $ dir Pack_1.class
   Pack_1.class ・・・・・・・・・・これが前項でコンパイルされたクラスファイル
   $ mv Pack_1.class `ack ・・クラスファイルをディレクトリPackに移動する
   $ dir Pack
   Pack_1.class
   $ _

import文

   パッケージを利用する時、import文でパッケージの在処を指定すると、ソースファイルの書き方が簡単になる。
  import文の書き方は色々ある。その1つは次の書き方である。

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

   この場合、指定したパッケージに含まれる指定したクラスだけを使用する事が出来る。
  したがって、あるパッケージに含まれるクラスclass1とclass2を使いたい時は、複数のimport文を書かなければならない。

   import パッケージ名.class1;
   import パッケージ名.class2;

   これは面倒なので、ここでは次の書き方を推奨する。

   import パッケージ名.*;

   ここで「*」は「全てのクラス」を意味する。したがって、この書き方により、指定したパッケージに含まれる全てのクラスを利用する事が出来る。
  例えば、いま作成したパッケージPackの全てのクラスを利用するには次のように書く。

   import Pack.*;

   import文はpackage文と同じように、そのソースファイルの最初の文にしなければならない。
  ただし、import文はpackage文を同時に使う場合は、import文を先に書く。

   import文
   package文

   もちろんこれらの文に先だってコメントを置く事は構わない。

   実際にパッケージPackを使用するサンプルアプリケーションを示す。

   サンプル:UsePack.java

   //
   //UsePack.java---パッケージを使う
   //
   import Pack.*;

   public class UsePack {
    public static void main(String[ ] args) {
     Pack_1 p = new Pack_1( );
     p.show( );
    }
   }

   このアプリケーションでは、まずimport文で使用するパッケージを指定している。

   import Pack.*;

   そして、パッケージPackに含まれるPack_1というクラスを利用している。

   Pack_1 p = new Pack_1( ); ・・・Pack_1のインスタンスを生成し
   p.show( ); ・・・・・・・・・・・・・・・・メソッドを呼び出す

   サンプルの実行例

   $ java UsePack
   Pack_1 : show
   $ _

   これは、運がいい場合である。運が悪いと次のように実行時エラーになる事もある。

   $ java UsePack
   Exception in thread "main" java.lang.NoClassDefFoundError: UsePack
   $ _

   それどころか、コンパイルすら出来ない場合もある。

   $ javac UsePack.java
   UsePack.java:4:パッケージPackがimportに見つかりません。
   import Pack.*;
       ^
   エラー1個
   $ _

   このように、ある環境ではうまくパッケージが使えたのに、ある環境では実行時エラーになったり、コンパイルエラーになったりする。
  この違いはどこから来るのだろう。それを次に解明する。

パッケージとディレクトリ

   前節のアプリケーションである環境ではうまくパッケージが使えたのに、
  ある環境では実行時エラーになったり、コンパイルエラーになったりしたのは、javaの処理系がパッケージを探すメカニズムに原因がある。
  なお、javaの処理系がパッケージを探すメカニズムは、処理系により異なる。
  以下の説明は、javaの処理系としてUNIX系のJDKを想定している。

環境変数CLASSPATH

   ソースファイルの先頭に次の記述があったとする。

   import Pack.*;

   この場合、javaはPackをパッケージ名と認識し、同名のディレクトリPackからパッケージを検索する。
  問題は、ディレクトリPackがどこにあるかである。
  これは、環境変数CLASSPATHが定義されているか、いないかによって異なる。

   ※補:環境変数やディレクトリは、UNIX固有の概念である。他のOSでjavaを使っている場合は、そのOSにおけるやり方に従う事。

   まず、環境変数CLASSPATHが定義されていない場合であるが、このとき検索の起点はカレントディレクトリになる。
  したがって、この場合は、次のディレクトリからパッケージPackが検索される。

   ./Pack ・・・・・カレントディレクトリのしたにあるサブディレクトリPack

   次に環境変数CLASSPATHが定義されている場合であるが、次のように2つのディレクトリdir1、dir2が設定されているとする。

   CLASSPATH=dir1:dir2

   この場合、パッケージPackのディレクトリは次のように検索される。

   ・ まずディレクトリdir1/Packが検索される
   ・ そこに指定のパッケージがなければ、次にdir2/Packが検索される
   ・ それでもパッケージが見つからなければパッケージの検索に失敗する

   なお環境変数CLASSPATHに1つでもディレクトリを登録すると、カレントディレクトリは検索の起点から除外される。
  例えば、環境変数CLASSPATHが次のように設定されているとする。

   CLASSPATH=/usr/local/jdk1.3.1/lib

   この場合は、ディレクトリ/usr/local/jdk1.3.1/libだけが検索の起点となり、カレントディレクトリ.は検索の起点から除外される。
  したがって、カレントディレクトリ.も検索の起点に含めたい時は、環境変数CLASSPATHに登録する必要がある。

   CLASSPATH=/usr/local/jdk1.3.1/lib:.

パッケージとディレクトリ

   既に説明したようにパッケージは、パッケージ名と同じディレクトリを作成し、そこにファイルする。つまり、次の関係が成立する。

   パッケージ名=ディレクトリ名

   したがって、import文で指定する名前は、パッケージ名であると同時にディレクトリ名であるとも言える。

   import Pack.*; ←この部分はパッケージ名であり、ディレクトリ名でもある

   つまり、import文の一般形は次の形をしていると考える事が出来る。

   import ディレクトリ名.クラス名
    または
   import ディレクトリ名.*

   この流儀で行くと、import文でディレクトリの階層を表現する事も出来る。

   import dir1.dir2.dir3.*

   これは、ディレクトリdir1/dir2にあるパッケージdir3に含まれる全てのクラスを使う事を宣言している。
  この場合、dir1、dir2はディレクトリ名であり、同時にパッケージ名であるかもしれない。
  しかし、再度のdir3はディレクトリ名であると同時に、必ずパッケージ名でなければならない。

   import dir1.dir2.dir3.* ←ここはディレクトリ名であると同時にパッケージ名でなければならない

デフォルトパッケージ

   所属するパッケージを指定するのにpackage文を使った。

   package パッケージ名; ・・・所属するパッケージ名を指定する

   class A { ・・・・・・・・・・・・・・このクラスは指定したパッケージに所属する
     …
   }

   ところが、前章までのプログラムでは、package文を使わないで来た。
  ソースファイルの先頭にpackage文を書かないと、そのファイルにあるクラスはデフォルトパッケージに入る。
   デフォルトパッケージというのは、要するにカレントディレクトリにあるパッケージである。
  デフォルトパッケージを使うには、クラスファイルをカレントディレクトリに置く。
  そして、環境変数CLASSPATHを使ってクラスパスを設定している場合には、そこに.(カレントディレクトリ)を追加する。

   CLASSPATH=dir_1:・・・・:dir_n:.

次へ