パッケージ

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" を探しに行きます。複数のクラスパスがセットされている場合は、先頭から順番に探していき、最初に見つけたものをロードします。

パッケージの役割は、次のようにまとめられます。

名前解決の単位:完全限定名
同じクラス名でも、パッケージが異なれば(別のディレクトリに存在すれば)別の実装と解釈される。例えば、開発チーム A と B が同じクラス名 Customer を採用するとき、パッケージが同じだと、名前解決時にどちらを呼び出すか指定できない。これを衝突(競合)と呼ぶ。パッケージが異なれば、単純クラス名が同じでも、完全限定名は異なるので、明示的に何れを呼び出すのか指定できる。
配布単位: JAR
パッケージ単位で ZIP 圧縮して JAR ファイルを作成できる。利用するときには、当該 JAR ファイルの絶対パスをクラスパスにセットすれば、当該 JAR ファイル内のディレクトリ構造を、ネイティブのファイルシステムと同様に利用できる。例えば、100 個のクラスを含むパッケージを JAR ファイルにすれば、一つのファイルとして配布できる。パッケージ分割を機能単位で行っておけば、JAR を当該機能単位の整合性を保ったコードのセットとして配布/管理できる。
アクセス制御の単位
アクセス修飾子は、パッケージをアクセス制御の単位とする。パッケージ提供された利用者は、外部から呼び出せる public 修飾された API だけを意識すればよい。フレームワーク基盤のように利用するならば、protected 修飾されたコードを継承して利用するように制御できる。

コア・パッケージ

Java 環境では、便利な機能を持ったクラスを標準クラスライブラリとして実装しています。これらはカテゴリごとにパッケージ化されており、コア・パッケージと呼ばれます。

代表的なパッケージ:

java.lang
Java プログラム言語の設計にあたり基本的なクラスを提供します。全てのクラスのルートとなる Object クラス、文字列を参照する String クラス、基本データ型のラップクラス(Integer, Character 等のクラス)などが含まれます。
java.io
データストリーム、直列化、ファイルシステムによるシステム入出力用に提供されています。
java.applet
アプレットの作成、およびアプレットとアプレットコンテキストとの通信に使用するクラスの作成に必要なクラスを提供します。
java.awt
ユーザインタフェースの作成と、グラフィックスとイメージのペイントのためのクラスがすべて含まれています。JDK1.2 (Java2) 以降から Swing に拡張された。
java.beans
JavaBeans の開発に関連するクラスが含まれています。
java.net
ネットワーク対応アプリケーションを実装するためのクラスを提供します。
java.util
このパッケージには、コレクションフレームワーク、従来のコレクションクラス、イベントモデル、日付と時刻の機構、国際化、およびさまざまなユーティリティクラス (文字列トークナイザ、乱数ジェネレータ、ビット配列) が含まれています。
javax.swing
GUI (Graphical User Interface) コンポーネントで、 JFC (Java Foundation Classes) の一部。すべてのプラットフォームで可能な限り同じように機能する、「軽量」(Java 共通言語) コンポーネントのセットを提供します。 AWT (Abstract Window Toolkit) の機能強化(継承)として実装。AWT が実行環境のウィンドウシステム特有のコードを利用しているのに対して、 Swing は完全に Java だけで作られたコンポーネント。
org.omg.CORBA
OMG CORBA API の Java プログラミング言語 (ORB クラスを含む) へのマッピングを提供します。

大量のパッケージのそれぞれに大量のクラスが定義されているので、 API 仕様の確認をすると良いでしょう。

パッケージの作成

パッケージは、既存のパッケージだけではなく、自分で作成することも出来ます。具体的には、パッケージに含めたいファイルの先頭でパッケージ宣言するだけです。

package パッケージ名;

パッケージ宣言は一つのファイルの先頭で一回だけ記述できます。つまり、一つのパッケージにしか含めることは出来ません。

パッケージ名は、クラスファイルが保存されるディレクトリ(フォルダ)のパス情報を記述したものです。つまり、基準ディレクトリから、当該クラスファイルが存在するディレクトリまでのパスを記述したものです。ディレクトリ間の区切り文字はピリオド "." です。通常は、 Windows 系のディレクトリ区切り文字は "\"、 UNIX 系の区切り文字は "/" です。 Java ではパッケージの区切り文字にピリオドを使います。

パッケージ名を解釈するときに利用する基準ディレクトリは、特別に指定しない限りはカレントディレクトリです。通常は、利用しているシステムの CLASSPATH 変数で基準ディレクトリを明示しておきます。

パッケージの利用

既存のパッケージに含まれるクラスを利用するクラスが記述されたファイルの冒頭で、 import 文を記述します。但し、 package 文も記述する場合は、 package 文の方が先になります。

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

指定したクラスの全てのクラスを利用する可能性があれば、クラス名の部分を "*" で記述します:

import パッケージ名.*;

複数のパッケージン(に含まれるクラス)をインポートしたければ、繰り返し import 文を書きます:

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

このソースをパッケージに含めたい場合は、インポート文の上にパッケージ宣言を書きます:

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


Copyright © 2001-2005 SUGAI, Manabu. All Rights Reserved.
SEO [PR] !uO z[y[WJ Cu