Java 101:パッケージはクラスとインターフェースを整理します

なぜ車輪の再発明をするのですか?その決まり文句は、一部の開発者が異なるプログラムに対して同じコードを頻繁に書き直すソフトウェア開発に適用されます。このアプローチの2つの欠点は次のとおりです。

  1. 時間を無駄にします
  2. デバッグされたコードにバグが発生する可能性があります

同じコードを書き直す代わりに、多くのソフトウェア開発環境には、頻繁に使用されるコードを整理するライブラリツールが用意されています。開発者は、再利用可能なコードのデバッグを終了すると、ツールを使用してそのコードをライブラリ(さまざまなプログラムで使用するために頻繁に使用されるコードを含む1つ以上のファイル)に保存します。プログラムの構築中に、コンパイラーまたはライブラリー・ツールはライブラリーにアクセスして、プログラムのライブラリー参照コードをプログラムに接続します。

ライブラリはJavaの基本です。それらは、部分的に、JVMのクラスローダーがクラスファイルを見つけることを可能にします。(クラスローダーについては、今後の記事で説明します。)そのため、Javaのライブラリは一般にクラスライブラリとして知られています。ただし、Javaはクラスライブラリをパッケージと呼びます。

この記事ではパッケージについて説明します。クラスとインターフェイスのパッケージを作成する方法、パッケージ化されたクラスとインターフェイスをインポートする(つまり、プログラムに取り込む)方法、ハードドライブにパッケージを移動する方法、およびjarファイルを使用してパッケージをカプセル化する方法を示します。

注意
この記事の単一パッケージの実験は、MicrosoftWindows固有のものです。この実験をWindows以外のプラットフォームに簡単に推定できるはずです。

パッケージとは何ですか?

パッケージには、クラスとインタフェースのコレクションです。各パッケージには独自の名前があり、その最上位(つまり、ネストされていない)クラスとインターフェイスを個別の名前空間または名前コレクションに編成します。同じ名前のクラスとインターフェイスを同じパッケージに表示することはできませんが、個別の名前空間が各パッケージに割り当てられるため、異なるパッケージに表示される可能性があります。

実装の観点からは、パッケージのクラスとインターフェイスをディレクトリのクラスファイルと同等にするのと同様に、パッケージをディレクトリと同等にすることが役立ちます。パッケージを実装するための他のアプローチ(データベースの使用など)を覚えておいてください。そのため、パッケージを常にディレクトリと同一視する習慣を身に付けないでください。ただし、多くのJVMはディレクトリを使用してパッケージを実装するため、この記事ではパッケージとディレクトリを同一視します。 Java 2 SDKは、クラスとインターフェイスの膨大なコレクションを、パッケージ内のパッケージのツリーのような階層に編成します。これは、ディレクトリ内のディレクトリに相当します。この階層により、Sun Microsystemsはこれらのクラスとインターフェースを簡単に配布(および簡単に操作)できます。 Javaのパッケージの例は次のとおりです。

  • java.lang:言語に関連するクラスのコレクション、などObjectStringして整理、javaパッケージのlangサブパッケージ
  • java.lang.ref:参照関連の語学教室、などのコレクションSoftReferenceReferenceQueueで編成さ、refのサブサブパッケージjavaパッケージのlangサブパッケージ
  • javax.swing:パッケージのサブパッケージに編成されたJButton、などのSwing関連のコンポーネントクラスおよびなどのインターフェイスのコレクションButtonModeljavaxswing

ピリオド文字はパッケージ名を区切ります。たとえば、javax.swingでは、ピリオド文字でパッケージ名javaxとサブパッケージ名を区切りますswing。ピリオド文字は、プラットフォームに依存しないスラッシュ文字(/)、バックスラッシュ文字(\)、またはディレクトリベースのパッケージ実装のディレクトリ名、階層型データベースベースのパッケージ実装のデータベースブランチなどを区切るその他の文字に相当します。 。

ヒント
同じディレクトリに同じ名前のファイルとディレクトリの両方を保存できないのと同じように、同じパッケージに同じ名前のクラスまたはインターフェイスとパッケージを保存することはできません。たとえば、という名前のパッケージ与えられたaccounts、あなたはパッケージと名前のクラスの両方格納することはできませんpayableでしaccounts。名前の競合を避けるために、クラス名とインターフェイス名の最初の文字を大文字にし、パッケージ名の最初の文字を小文字にします。前の例を使用して、店舗のクラスPayableパッケージ内accountsのようにaccounts.Payable、パッケージpayableのパッケージでaccountsのようにaccounts.payable。これと他の命名規則の詳細については、SunのJavaプログラミング言語コード規則を参照してください

クラスとインターフェースのパッケージを作成する

すべてのソースファイルのクラスとインターフェイスは、パッケージに編成されます。ではpackageディレクティブの不在、これらのクラスとインタフェースは、名前のパッケージ(JVMは、現在のディレクトリのJavaプログラムがWindowsを経由してその実行を開始ディレクトリとしてみなすディレクトリに属しているjava.exe、またはOS-同等のプログラムと何のサブパッケージが含まれていません) 。ただし、packageディレクティブがソースファイルにある場合、そのディレクティブはそれらのクラスとインターフェイスのパッケージに名前を付けます。次の構文を使用してpackage、ソースコードでディレクティブを指定します。

'package' packageName ['。' subpackageName ...] ';'

packageディレクティブはで始まるpackageキーワード。パッケージに名前を付ける識別子、、がすぐpackageNameに続きます。クラスとインターフェースが内のサブパッケージ(あるレベル)に表示されるpackageName場合、1つ以上のピリオドで区切らsubpackageNameれた識別子がpackageName。の後に表示されます。次のコードフラグメントは、packageディレクティブのペアを示しています。

パッケージゲーム; パッケージgame.devices;

The first package directive identifies a package named game. All classes and interfaces appearing in that directive's source file organize in the game package. The second package directive identifies a subpackage named devices, which resides in a package named game. All classes and interfaces appearing in that directive's source file organize in the game package's devices subpackage. If a JVM implementation maps package names to directory names, game.devices maps to a game\devices directory hierarchy under Windows and a game/devices directory hierarchy under Linux or Solaris.

Caution
Only one package directive can appear in a source file. Furthermore, the package directive must be the first code (apart from comments) in that file. Violating either rule causes Java's compiler to report an error.

To help you get comfortable with packages, I've prepared an example that spans all topics in this article. In this section, you learn how to create the example's package. In later sections, you will learn how to import a class and an interface from this package, how to move this package to another location on your hard drive and still access the package from a program, and how to store the package in a jar file. Listing 1 presents the package's source code:

Listing 1. A.java

// A.java package testpkg; public class A { int x = 1; public int y = 2; protected int z = 3; int returnx () { return x; } public int returny () { return y; } protected int returnz () { return z; } public interface StartStop { void start (); void stop (); } } class B { public static void hello () { System.out.println ("hello"); } } 

Listing 1 introduces the source code to your first named package. The package testpkg; directive names that package testpkg. Within testpkg are classes A and B. Within A are three field declarations, three method declarations, and an inner interface declaration. Within B is a single method declaration. The entire source code stores in A.java because A is a public class. Our task: Turn this source code into a package that consists of two classes and an inner interface (or a directory that contains three classfiles). The following Windows-specific steps accomplish that task:

  1. Open a Windows command window and ensure you are in the c: drive's root directory (the main directory—represented by an initial backslash (\) character). To do that, type the c: command followed by the cd \ command. (If you use a different drive, replace c: with your chosen drive. Also, do not forget to press the Enter key after typing a command.)
  2. Create a testpkg directory by typing md testpkg. Note: When following this article's steps, do not type periods after the commands.
  3. Make testpkg the current directory by typing cd testpkg.
  4. Use an editor to enter Listing 1's source code and save that code to an A.java file in testpkg.
  5. Compile A.java by typing javac A.java. You should see classfiles A$StartStop.class, A.class, and B.class appear in the testpkg directory.

Figure 1 illustrates Steps 3 through 5.

Congratulations! You have just created your first package. Think of this package as containing two classes (A and B) and A's single inner interface (StartStop). You can also think of this package as a directory containing three classfiles: A$StartStop.class, A.class, and B.class.

Note
To minimize package name conflicts (especially among commercial packages), Sun has established a convention in which a company's Internet domain name reverses and prefixes a package name. For example, a company with x.com as its Internet domain name and a.b as a package name (a) followed by a subpackage name (b) prefixes com.x to a.b, resulting in com.x.a.b. My article does not follow this convention because the testpkg package is a throw-away designed for teaching purposes only.

Import a package's classes and interfaces

Once you have a package, you will want to import classes and/or interfaces—actually, class and/or interface names—from that package to your program, so it can use those classes and/or interfaces. One way to accomplish that task is to supply the fully qualified package name (the package name and all subpackage names) in each place where the reference type name (the class or interface name) appears, as Listing 2 demonstrates:

Listing 2. Usetestpkg1.java

// Usetestpkg1.java class Usetestpkg1 implements testpkg.A.StartStop { public static void main (String [] args) { testpkg.A a = new testpkg.A (); System.out.println (a.y); System.out.println (a.returny ()); Usetestpkg1 utp = new Usetestpkg1 (); utp.start (); utp.stop (); } public void start () { System.out.println ("Start"); } public void stop () { System.out.println ("Stop"); } } 

By prefixing testpkg. to A, Usetestpkg1 accesses testpkg's class A in two places and A's inner interface StartStop in one place. Complete the following steps to compile and run Usetestpkg1:

  1. Open a Windows command window and make sure you are in the c: drive's root directory.
  2. Ensure the classpath environment variable does not exist by executing set classpath=. (I discuss classpath later in this article.)
  3. Use an editor to enter Listing 2's source code and save that code to a Usetestpkg1.java file in the root directory.
  4. Compile Usetestpkg1.java by typing javac Usetestpkg1.java. You should see classfile Usetestpkg1.class appear in the root directory.
  5. Type java Usetestpkg1 to run this program.

Figure 2 illustrates Steps 3 through 5 and shows the program's output.

According to Usetestpkg1's output, the main() method's thread successfully accesses testpkg.A's y field and calls the returny() method. Furthermore, the output shows a successful implementation of the testpkg.A.StartStop inner interface.

For Usetestpkg1, prefixing testpkg. to A in three places doesn't seem a big deal. But who wants to specify a fully qualified package name prefix in a hundred places? Fortunately, Java supplies the import directive to import a package's public reference type name(s), so you do not have to enter fully qualified package name prefixes. Express an import directive in source code via the following syntax:

'import' packageName [ '.' subpackageName ... ] '.' ( referencetypeName | '*' ) ';' 

An import directive consists of the import keyword immediately followed by an identifier that names a package, packageName. An optional list of subpackageName identifiers follows to identify the appropriate subpackage (if necessary). The directive concludes with either a referencetypeName identifier that identifies a specific class or interface from the package, or an asterisk (*) character. If referencetypeName appears, the directive is a single-type import directive. If an asterisk character appears, the directive is a type-on-demand import directive.

Caution
As with the package directive, import directives must appear before any other code, with three exceptions: a package directive, other import directives, or comments.

The single-type import directive imports the name of a single public reference type from a package, as the following code fragment demonstrates:

import java.util.Date; 

The previous single-type import directive imports class name Date into source code. As a result, you specify Date instead of java.util.Date in each place that class name appears in source code. For example, when creating a Date object, specify Date d = new Date (); instead of java.util.Date d = new java.util.Date ();.

単一タイプのimportディレクティブで注意してください。import次のコードフラグメントが示すように、コンパイラがソースファイルでも宣言されている参照型名を指定する単一型ディレクティブを検出すると、コンパイラはエラーを報告します。

import java.util.Date; クラス日付{}

コンパイラーは、コードフラグメントを、同じDate名前の2つの参照型を導入する試みと見なします。