Java パッケージ(package)

クラスをより良く整理するために、Java はクラス名の名前空間を区別するためのパッケージメカニズムを提供します。

パッケージの役割

  • 1. 機能が似ている、または関連するクラスやインターフェースを同じパッケージにまとめることで、クラスの検索と使用を容易にします。

  • 2. フォルダのように、パッケージもツリー構造のディレクトリ方式で保存されます。同じパッケージ内のクラス名は異なり、異なるパッケージ内のクラス名は同じにすることができます。同時に2つの異なるパッケージ内の同じクラス名のクラスを呼び出すときは、パッケージ名を付けて区別する必要があります。したがって、パッケージは名前の衝突を避けることができます。

  • 3. パッケージはアクセス権限も制限します。パッケージアクセス権限を持つクラスだけが、あるパッケージ内のクラスにアクセスできます。

Java がパッケージ(package)というメカニズムを使用するのは、命名の衝突を防ぎ、アクセスを制御し、クラス、インターフェース、列挙型、アノテーションなどを見つけて位置を特定するためです。

パッケージ文の構文は次のとおりです:

package pkg1[.pkg2[.pkg3…]];

例えば、ある Something.java ファイルの内容が次のような場合

package net.java.util; public class Something{ ... }

そのパスは次のようになります。net/java/util/Something.javaこのように保存します。package(パッケージ)の役割は、異なる Java プログラムを分類して保存し、他の Java プログラムからより簡単に呼び出せるようにすることです。

パッケージ(package)は、相互に関連する型(クラス、インターフェース、列挙型、アノテーション)のグループとして定義でき、これらの型にアクセス保護と名前空間管理の機能を提供します。

以下は Java のパッケージの一部です:

  • java.lang- 基本的なクラスをパッケージ化する
  • java.io- 入出力機能を含む関数

開発者は自分で一連のクラスやインターフェースなどをパッケージ化し、独自のパッケージを定義できます。実際の開発ではこれを行うことが推奨されます。自分でクラスの実装を完了した後、関連するクラスをグループ化することで、他のプログラマーがどのクラス、インターフェース、列挙型、アノテーションなどが関連しているかをより簡単に判断できるようになります。

パッケージは新しい名前空間(namespace)を作成するため、他のパッケージ内のどの名前とも命名の衝突は発生しません。パッケージというメカニズムを使用すると、アクセス制御をより簡単に実現でき、関連するクラスの位置を特定しやすくなります。


パッケージの作成

パッケージを作成するときは、そのパッケージに適切な名前を付ける必要があります。その後、他のソースファイルがこのパッケージが提供するクラス、インターフェース、列挙型、またはアノテーション型を含む場合は、必ずこのパッケージの宣言をソースファイルの先頭に置く必要があります。

パッケージ宣言はソースファイルの最初の行にある必要があります。各ソースファイルにはパッケージ宣言を1つだけ置くことができ、そのファイル内のすべての型に適用されます。

ソースファイルでパッケージ宣言を使用しない場合、その中のクラス、関数、列挙型、アノテーションなどは、無名パッケージ(unnamed package)に配置されます。

例

例を見てみましょう。この例では、animals というパッケージを作成します。通常、クラスやインターフェースの名前との衝突を避けるために小文字を使用して命名します。

animals パッケージにインターフェース(interface)を追加します:

Animal.java ファイルのコード:

/*ファイル名: Animal.java*/ package animals; interface Animal { public void eat(); public void travel(); }

次に、同じパッケージにそのインターフェースの実装を追加します:

MammalInt.java ファイルのコード:

package animals; /*ファイル名 : MammalInt.java*/ public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); } }

次に、これら2つのファイルをコンパイルし、animals というサブディレクトリに配置します。 以下のコマンドで実行します:

$ mkdir animals
$ cp Animal.class  MammalInt.class animals
$ java animals/MammalInt
Mammal eats
Mammal travel

import キーワード

あるパッケージのメンバーを使用するには、Java プログラムでそのパッケージを明示的にインポートする必要があります。

Java では、importキーワードは、他のクラスまたはパッケージで定義された型をインポートして、現在のソースファイルでこれらの型を使用できるようにするために使用されます。

importキーワードは、他のパッケージ内のクラス、インターフェース、または静的メンバーをインポートするために使用されます。これにより、コード内で他のパッケージのクラスを完全なパッケージ名を指定せずに直接使用できます。

Java ソースファイルでは、import 文は Java ソースファイルの先頭に置く必要があります。その構文は次のとおりです:

import package1[.package2…].(classname|*);

import 文は package 文の後に置きます:

//最初の非コメント行は package 文です。 package com.example; //import 文は他のパッケージ内のクラスをインポートします。 import java.util.ArrayList; import java.util.List; //クラスの定義 public class MyClass { //クラスのメンバーとメソッド }

あるパッケージ内で、クラスが同じパッケージ内の別のクラスを使用したい場合、そのパッケージ名は省略できます。

import 文を使用して特定のクラスをインポートできます:

import com.サンプル.MyClass;

これにより、現在のソースファイルで MyClass クラスのメソッド、変数、または定数を直接使用できます。

ワイルドカードを使用することもできます*パッケージ全体またはパッケージのサブパッケージをインポートするには:

import com.サンプル.mypackage.*;

これにより、次のものをインポートできますcom.サンプル.mypackageパッケージ内のすべてのクラスをインポートして、現在のソースファイルでそのパッケージ内の任意のクラスのメソッド、変数、または定数を使用できます。注意点として、ワイルドカードを使用して*パッケージ全体をインポートする場合、パッケージ内のクラスのみがインポートされ、パッケージ内のサブパッケージはインポートされません。

クラスまたはパッケージをインポートするときは、クラスの完全修飾名またはパッケージの完全修飾名を指定する必要があります。完全修飾名はパッケージ名とクラス名の組み合わせで構成され、ドット.で区切られます。

例

import java.util.ArrayList; // java.util パッケージから ArrayList クラスをインポートする
import java.util.*; // java.util パッケージのすべてのクラスをインポートする

import com.example.MyClass; // com.example パッケージから MyClass クラスをインポートする
import com.example.*; // com.example パッケージのすべてのクラスをインポートする

例

以下の payroll パッケージには既に Employee クラスが含まれています。次に、payroll パッケージに Boss クラスを追加します。Boss クラスが Employee クラスを参照するとき、payroll プレフィックスを使用する必要はありません。Boss クラスの例は次のとおりです。

Boss.java ファイルのコード:

package payroll; public class Boss { public void payEmployee(Employee e) { e.mailCheck(); } }

Boss クラスが payroll パッケージにない場合はどうなるでしょうか?その場合、Boss クラスは他のパッケージのクラスを参照するために、以下のいずれかの方法を使用する必要があります。

クラスの完全修飾名を使用して記述します。例:

payroll.Employee

用 importワイルドカードを使用してキーワードでインポートする*:

import payroll.*;

使用importキーワードで Employee クラスをインポートします:

import payroll.Employee;

注意:

クラスファイルには任意の数の import 宣言を含めることができます。import 宣言は、パッケージ宣言の後、クラス宣言の前に置く必要があります。


package のディレクトリ構造

クラスをパッケージに配置すると、主に2つの結果が生じます:

  • パッケージ名はクラス名の一部になります。前述のとおりです。
  • パッケージ名は、対応するバイトコードが置かれているディレクトリ構造と一致している必要があります。

以下は、自分自身の Java ファイルを管理する簡単な方法です:

クラス、インターフェースなどの型のソースコードをテキストファイルに置きます。このファイルの名前はその型の名前で、拡張子は .java です。例:

//ファイル名 : Car.java package vehicle; public class Car { //クラスの実装 }

次に、ソースファイルをディレクトリに置きます。このディレクトリは、クラスが属するパッケージの名前に対応している必要があります。

....\vehicle\Car.java

正しいクラス名とパスは次のようになります:

  • クラス名 -> vehicle.Car

  • パス名 -> vehicle\Car.java (Windows システムの場合)

通常、企業はインターネットドメイン名を逆にした形式をパッケージ名として使用します。例えば、ドメイン名が example.com の場合、すべてのパッケージ名は com.サンプル で始まります。パッケージ名の各部分はサブディレクトリに対応します。

例えば、あるcom.サンプル.testパッケージがある場合、このパッケージには サンプル.java というソースファイルが含まれています。その場合、対応する一連のサブディレクトリが次のように必要になります:

....\com\サンプル\test\サンプル.java

コンパイル時、コンパイラはパッケージ内で定義された各クラス、インターフェースなどの型ごとに異なる出力ファイルを作成します。出力ファイルの名前はその型の名前で、拡張子として .class が付加されます。 例:

//ファイル名: サンプル.java package com.サンプル.test; public class サンプル { } class Google { }

次に、-d オプションを使用してこのファイルをコンパイルします。次のようにします:

$javac -d . サンプル.java

これにより、コンパイルされたファイルは次のように配置されます:

.\com\サンプル\test\サンプル.class
.\com\サンプル\test\Google.class

次のようにして、すべてをインポートできます \com\サンプル\test\ で定義されているクラス、インターフェースなど:

import com.サンプル.test.*;

コンパイル後の .class ファイルは .java ソースファイルと同様に、配置するディレクトリはパッケージ名に対応している必要があります。ただし、.class ファイルのパスが対応する .java ファイルのパスと同じである必要はありません。ソースコードとクラスのディレクトリを分けて配置することもできます。

<path-one>\sources\com\サンプル\test\サンプル.java
<path-two>\classes\com\サンプル\test\Google.class

これにより、クラスディレクトリを他のプログラマーに共有でき、自分のソースコードを公開する必要はありません。この方法でソースコードとクラスファイルを管理することで、コンパイラとJava仮想マシン(JVM)がプログラムで使用されるすべての型を見つけることができます。

クラスディレクトリの絶対パスはclass path。システム変数CLASSPATHに設定されます。コンパイラとJava仮想マシンは、パッケージ名をクラスパスに追加して、.classファイルのパスを構築します。

<path-two>\classes がクラスパスで、パッケージ名が com.サンプル.test の場合、コンパイラとJVMは <path-two>\classes\com\サンプル\test 内で .class ファイルを探します。

クラスパスには複数のパスを含めることができ、複数のパスは区切り文字で区切る必要があります。デフォルトでは、コンパイラとJVMは現在のディレクトリを検索します。JARファイルはJavaプラットフォーム関連のクラスを含むため、そのディレクトリはデフォルトでクラスパスに含まれます。


CLASSPATH システム変数の設定

以下のコマンドで現在のCLASSPATH変数を表示します:

  • Windows プラットフォーム(DOSコマンドライン):C:\> set CLASSPATH
  • UNIX プラットフォーム(Bourne shell):# echo $CLASSPATH
現在のCLASSPATH変数の内容を削除:
  • Windows プラットフォーム(DOSコマンドライン):C:\> set CLASSPATH=
  • UNIX プラットフォーム(Bourne shell):# unset CLASSPATH; export CLASSPATH

CLASSPATH変数の設定:

  • Windows プラットフォーム(DOSコマンドライン): C:\> set CLASSPATH=C:\users\jack\java\classes
  • UNIX プラットフォーム(Bourne shell):# CLASSPATH=/home/jack/java/classes; export CLASSPATH
その他の拡張