Revised: May/21st/2005: Since: Jan./1st/2002
Java プログラムは、クラスやインタフェィスを extends
したり implements
することで組み立てた、クラスファイルの集合です。
数百個~数千個のクラス・ファイルの集団としてアプリケーションを考えたとき、内部で利用しているクラスを、他のアプリケーションから利用されたくないことがあります(アクセス制御)。また、アプリケーションを配布するとき、数百個~数千個のファイルの間のバージョンの整合性を維持したり、他のアプリケーションと混ざらないようにしたり、配布したりするのは大変なことです。また、大量のクラス・ファイル間で、名前が重複しないようにしなくてはならなくなったとしたら、現実的ではありません。
コンパイル型言語である C/C++ や COBOL, PL/I の場合は、コンパイル/ビルド時に、マクロ展開によって複雑な処理を外出しにして、連係編集によって関連するオブジェクトモジュールを内部に取り込み、実行可能なロードモジュールに纏め上げることができます。一方、Java の場合は、コンパイル時には連係編集のような処理は行われないので、いわばオブジェクト・モジュール(CSECT)単位のクラス・ファイルが剥き出しのままネイティブ・ファイル・システム上に存在することになります。これらをそのまま管理することは現実的ではありません。
このようなときに、クラスやインタフェィスのまとまりをパッケージ (package
) にして、JAR ファイルという一つのファイルに纏め上げることができます。また、必要があればアクセス修飾子でアクセス制限して、パッケージ内部のコードが不用意に呼び出されないように保護できます。また、既存のパッケージをインポート (import
) して利用することも出来ます。
これれから説明するとおり、パッケージはクラスが含まれるディレクトリ構造を反映したものです。
例えば、クラスファイル "TestClass.class
" が、 "クラスパス\demo\myPackage\TestClass.class
" に存在するとき、クラス "TestClass
" はパッケージ "demo.myPacakge
" に属するように作成します。"TestClass
" を単純クラス名と呼び、"demo.myPackage.TestClass
" を完全限定名と呼びます。
逆に言うと、JVM は、完全限定名 "demo.myPackage.TestClass
" が呼び出されると、"クラスパス\demo\myPackage\TestClass.class
" を探しに行きます。複数のクラスパスがセットされている場合は、先頭から順番に探していき、最初に見つけたものをロードします。
パッケージの役割は、次のようにまとめられます。
Customer
を採用するとき、パッケージが同じだと、名前解決時にどちらを呼び出すか指定できない。これを衝突(競合)と呼ぶ。パッケージが異なれば、単純クラス名が同じでも、完全限定名は異なるので、明示的に何れを呼び出すのか指定できる。public
修飾された API だけを意識すればよい。フレームワーク基盤のように利用するならば、protected
修飾されたコードを継承して利用するように制御できる。Java 環境では、便利な機能を持ったクラスを標準クラスライブラリとして実装しています。これらはカテゴリごとにパッケージ化されており、コア・パッケージと呼ばれます。
代表的なパッケージ:
java.lang
Object
クラス、文字列を参照する String
クラス、基本データ型のラップクラス(Integer
, Character
等のクラス)などが含まれます。java.io
java.applet
java.awt
java.beans
java.net
java.util
javax.swing
org.omg.CORBA
大量のパッケージのそれぞれに大量のクラスが定義されているので、 API 仕様の確認をすると良いでしょう。
パッケージは、既存のパッケージだけではなく、自分で作成することも出来ます。具体的には、パッケージに含めたいファイルの先頭でパッケージ宣言するだけです。
package パッケージ名;
パッケージ宣言は一つのファイルの先頭で一回だけ記述できます。つまり、一つのパッケージにしか含めることは出来ません。
パッケージ名は、クラスファイルが保存されるディレクトリ(フォルダ)のパス情報を記述したものです。つまり、基準ディレクトリから、当該クラスファイルが存在するディレクトリまでのパスを記述したものです。ディレクトリ間の区切り文字はピリオド ".
" です。通常は、 Windows 系のディレクトリ区切り文字は "\
"、 UNIX 系の区切り文字は "/
" です。 Java ではパッケージの区切り文字にピリオドを使います。
パッケージ名を解釈するときに利用する基準ディレクトリは、特別に指定しない限りはカレントディレクトリです。通常は、利用しているシステムの CLASSPATH 変数で基準ディレクトリを明示しておきます。
既存のパッケージに含まれるクラスを利用するクラスが記述されたファイルの冒頭で、 import
文を記述します。但し、 package
文も記述する場合は、 package
文の方が先になります。
import パッケージ名.クラス名;
指定したクラスの全てのクラスを利用する可能性があれば、クラス名の部分を "*
" で記述します:
import パッケージ名.*;
複数のパッケージン(に含まれるクラス)をインポートしたければ、繰り返し import
文を書きます:
import パッケージ名.クラス名; import パッケージ名.クラス名; import パッケージ名.クラス名;
このソースをパッケージに含めたい場合は、インポート文の上にパッケージ宣言を書きます:
package パッケージ名; import パッケージ名.クラス名;