6.2 インポート
6.2.1 完全限定名を省略する
再利用可能なクラスをパッケージ化し、便利な機能を提供するクラスライブラリを数多く設計することで、組織の開発能力は大幅に向上し、短期間で優れたソフトウェアを開発することができるようになるでしょう。しかし、一方で多くのライブラリを併用すると、クラスやインタフェースを利用するたびに長い完全限定名を指定しなければならなくなります。長い識別子は、プログラマの簡単な過ちを誘う要因となるため、避けたいものです。
そこで、Java 言語では特定のパッケージのクラスやインタフェースを単純名で参照できるようにするインポートと呼ばれる機能があります。型をインポートすれば、異なるパッケージで公開されている型を単純名で利用できるようになります。つまり、パッケージ名の省略が可能になるのです。型をインポートするには、インポート宣言を行う必要があります。
インポート宣言はどこでも行えるわけではありません。パッケージ宣言同様に、クラスやインタフェースなどの型を宣言する前に指定する必要がありますが、パッケージ宣言よりは後に記述しなければなりません。インポート宣言は import キーワードを用いて次のように宣言します。
import 型;
インポート宣言では、import キーワードに続いて、インポートする型をパッケージ名も含めた完全限定名で指定します。正しく型がインポートされれば、インポート宣言で指定した型は、そのソースファイル内では単純名で名前付きパッケージの型を参照することができるようになります。インポートする対象の型が複数ある場合は、インポート宣言を複数指定します。
package dokuhon.drawing; public class Point { public final int x , y; public Point(int x , int y) { this.x = x; this.y = y; } public String toString() { return super.toString() + " {" + x + " , " + y + "}"; } }
import dokuhon.drawing.Point; class Test { public static void main(String args[]) { Point pt1 = new Point(400 , 300); dokuhon.drawing.Point pt2 = new Point(200 , 120); System.out.println(pt1); System.out.println(pt2); } }
>java Test dokuhon.drawing.Point@5224ee {400 , 300} dokuhon.drawing.Point@f6a746 {200 , 120}
コード1では、名前付きパッケージの型 dokuhon.drawing.Point 型を Point.java ファイルで宣言し、この Point 型を無名パッケージ Test クラスで利用しています。通常は完全限定名で参照しなければなりませんが、Test.java ファイルでは Point 型をインポートしているため、単純名で参照することができるのです。もちろん、インポートした型を完全限定名で利用しても意味は同じなので問題はありません。
インポート宣言は長い名前を省略できるため、開発者にとっては面倒が少なくなるため便利です。しかし、1 つや 2 つであれば簡単ですが、数百もの型を利用するプログラムですべてをインポートすることを考えた場合、その作業だけで時間が削られてしまいます。
import dokuhon.drawing.Point; import dokuhon.drawing.Size; import dokuhon.drawing.Color; import dokuhon.drawing.Font; ...
とても面倒な作業ですね。この問題を解決するには、特定の型だけをインポートするのではなく、パッケージごとインポートしてしまいます。パッケージごとインポートした場合は、パッケージ内で公開されているすべての型が単純名で参照できるようになります。パッケージのすべての型をインポートするには、次のようなインポート宣言を行います。
import パッケージ名 . *;
この宣言を行うことによって、指定したパッケージで公開されている型をすべてインポートしたことになります。このインポート宣言をオンデマンドの型インポート宣言と呼びます。これに対して、前述した特定の型だけをインポートする宣言を単一の型インポート宣言と呼んでいます。多くの Java プログラマは、特別な事情がない限りオンデマンドの型インポート宣言を用います。
package dokuhon.animal; public interface Animal {}
package dokuhon.animal; public class Kitty implements Animal {}
package dokuhon.animal; public class Puppy implements Animal {}
import dokuhon.animal.*; class Test { public static void main(String args[]) { Animal animal1 = new Kitty(); Animal animal2 = new Puppy(); System.out.println(animal1); System.out.println(animal2); } }
>java Test dokuhon.animal.Kitty@5ff48b dokuhon.animal.Puppy@affc70
コード2では、dokuhon.animal パッケージに Animal インタフェースと Kitty 及び Puppy クラスを宣言しています。名前付きパッケージに含まれている型の多くを参照することが予想される場合、オンデマンドの型インポート宣言でパッケージに含まれるすべての型をインポートした方が効率的です。Test.java の先頭では、dokuhon.animal パッケージで公開されているすべての型をインポートしています。
ところで、パッケージ宣言とインポート宣言は、型宣言などの他の文とは違い、ソースファイルの先頭で記述しなければならないという特殊な性質を持っていました。さらには、インポート宣言はパッケージ宣言の後に記述しなければならないというルールもあります。これは、Java のソースファイルが、常に次のような構造であることを表しています。
パッケージ宣言 インポート宣言群 型宣言群
パッケージ宣言はソースファイルに常に 1 つです。インポート宣言群は型宣言の前であればいくつでも指定することが可能です。そして、その後にクラスやインタフェースの宣言を記述する型宣言群という構造になっています。この規則をコンパイル単位と呼びます。覚えておくと良いでしょう。
因みに、Java 言語はもっとも基本的な機能を提供する java.lang というクラスライブラリを暗黙的にインポートするというルールが存在します。java.lang パッケージには Object クラスや String クラスなどの欠かせないクラスが公開されています。
import java.lang.*;
すべてのコンパイル単位は、このように java.lang パッケージをインポートしていると理解してください。もちろん、明示的にインポートを記述してもかまいませんが、意味のある記述ではありません。