public
と宣言した場合に限り,それを宣言しているパッケージの外部からアクセス可能とする(6.6)。
パッケージの名前付けの構造は階層的とする(7.1)。パッケージのメンバは,そのパッケージのコンパイル単位内で宣言した,クラス及びインタフェース型(7.6),並びにそれ自体がコンパイル単位及びサブパッケージを含んでもよいサブパッケージとする。
パッケージは,ファイルシステム(7.2.1)又はデータベース(7.2.2)に格納できる。ファイルシステムに格納するパッケージは,単純な実装がクラスをたやすく検出できるように,コンパイル単位の構成に制約をもつ。いずれの場合でも,Javaプログラムに利用可能なパッケージの集合はホストシステムが決定するが,20,21及び22で規定した少なくとも三つの標準パッケージ
java.lang
,java.util
及び java.io
を常に含まなければならない。大部分のホスト環境では,この規格には規定していない標準パッケージ
java.applet
,java.awt
及び
java.net
もJavaプログラムで利用できる。
一つのパッケージは,複数のコンパイル単位で構成する(7.3)。コンパイル単位は,そのパッケージで宣言したすべての型に自動的にアクセス可能とし,さらにあらかじめ定義されたパッケージ
java.lang
で宣言した各型を自動的にインポートする。
一つのコンパイル単位は,次の三つの部分からなる。それぞれは省略可能とする。
package
宣言(7.4)。コンパイル単位が属するパッケージの完全限定名(6.7)を与える。
import
宣言(7.5)。他のパッケージの型を単純名で参照可能とする。
java
は,サブパッケージ
awt
,applet
,io
,lang
,net
及び util
をもつが,コンパイル単位はもたない。
java.awt
は image
というサブパッケージをもち,さらに,クラス及びインタフェース型の宣言を含む多くのコンパイル単位をもつ。
.
Q
はサブパッケージの完全限定名とする。
lang
,util
及び
io
という名前のパッケージ java
のサブパッケージ
(従ってそれらのサブパッケージの完全限定名は
java.lang
,java.util
及び
java.io
)は,すべてのJava処理系の標準部分であって,20,21及び22で規定される。多くのJava処理系は,規格
The Java Application Programming Interfaceで定義したパッケージ
java
の全集合を含む。
パッケージは,同じ名前の型宣言及びサブパッケージを含んではならない。そうでないときには,コンパイル時エラーを生じる。例を次に示す。
java.awt
は,サブパッケージ image
をもつので,image
という名前のクラス又はインタフェース型の宣言を含むことはできない(そして含んでいない)。
mouse
という名前のパッケージが存在し,そのパッケージ内に型
Button
(mouse.Button
として参照する)が存在すれば,mouse.Button
又は
mouse.Button.Click
という完全限定名をもつパッケージは存在できない。
COM.Sun.java.jag
が型の完全限定名ならば,完全限定名を
COM.Sun.java.jag
又は COM.Sun.java.jag.scrabble
とするパッケージは存在できない。
oliver
という名前のパッケージ及び oliver.twist
という名前の別のパッケージには特別なアクセス関係は存在せず,evelyn.wood
という名前のパッケージ及びevelyn.Waugh
という名前のパッケージの間にも特別なアクセス関係は存在しない。例えば,oliver.twist
という名前のパッケージ内のコードが,パッケージ oliver
内で宣言した型に,他のパッケージ内のコードよりもアクセスしやすいということはない。Javaの単純な処理系では,パッケージを局所的なファイルシステムに格納してもよい。他の処理系では,Javaのソースコード及び(又は)バイナリコードを,分散ファイルシステム又はデータベースの何らかの形式に格納してもよい。
COM gls jag java wnjディレクトリ
java
は,すべての標準Javaシステムの一部とする,標準Java
アプリケーションプログラミングインタフェースパッケージを含む。ディレクトリjag
,gls
及び wnj
は,この規格の三人の著者が,個人使用及び小グループ内で互いの共有のために作成したパッケージを含むかもしれない。ディレクトリCOM
には,パッケージに一意な名前を付けるために7.7で説明する規約を使った,会社から調達したパッケージを含んでいる。
さらに,ディレクトリ java
は,恐らく少なくとも次のサブディレクトリを含んでいる。
applet awt io lang net utilこれらは,標準Javaアプリケーションプログラミングインタフェースの一部として定義された標準パッケージ
java.applet
,java.awt
,java.io
,java.lang
,java.net
及び java.util
に対応する。
さらに,ディレクトリ util
の中を見れば,次のファイルを見つけるだろう。
BitSet.java Observable.java BitSet.class Observable.class Date.java Observer.java Date.class Observer.class Dictionary.java Properties.java Dictionary.class Properties.class EmptyStackException.java Random.java EmptyStackException.class Random.class Enumeration.java Stack.java Enumeration.class Stack.class Hashtable.java StringTokenizer.java Hashtable.class StringTokenizer.class NoSuchElementException.java Vector.java NoSuchElementException.class Vector.class各
.java
ファイルは,一つのクラス又はインタフェースの定義を含む一つのコンパイル単位(7.3)のソースを含み,対応する
.class
ファイルがコンパイルしたバイナリ形式を含む。
この単純なパッケージ構成において,Javaのある処理系は,パッケージ名の構成要素を連結し,ファイル名の分離子(ディレクトリ表示子)を隣接する構成要素間に挟んで,パッケージ名をパス名に変換する。例えば,この単純な構成をUNIXシステムで用いる場合,ファイル名の分離子は
/
なので,次のパッケージ名,
jag.scrabble.boardは,次のディレクトリ名へと変換される。
jag/scrabble/boardそして,
COM.Sun.sunsoft.DOEは次のディレクトリ名へと変換される。
COM/Sun/sunsoft/DOE
実際には,UNIX上の標準JavaSoft Java Developer's
Kitは,ディレクトリ集合を指定する CLASSPATH
環境変数を提供し,その各々をここに記述した一つのディレクトリとして扱う,という点でだけ,ここに記述した非常に単純な原則と異なる。名前付きパッケージ及び型の定義を捜して,これらのディレクトリを順に検索する。
ファイル名にASCII文字しか許さないシステム上でのUnicode文字のように,
パッケージ名の構成要素又はクラス名が,ホストのファイルシステムでの通常のディレクトリ名では正しく出現できない文字を含むかもしれない。便宜的に,その文字は,\u
xxxx
エスケープ(3.3)と同じように,例えば文字
@
にその文字の数値を与える4桁の16進数字を続けることで,エスケープすることができる。このとき次のパッケージ名
children.activities.crafts.papierM\u00e2ch\u00e9は,すべてUnicode文字を使って次のように書くことができる。
children.activities.crafts.papierMâchéさらに,これは次のディレクトリ名にマッピングされる。
children/activities/crafts/papierM@00e2ch@00e9文字
@
がホストのファイルシステムで有効でない文字ならば,Java識別子で有効でない他の文字を代わりに用いることも可能とする。
Javaは,そのようなデータベースが,ファイルに基づいた処理系におけるコンパイル単位上の制約
(7.6)を緩和することを可能とする。例えば,パッケージを格納するためにデータベースを使用するシステムは,コンパイル単位ごとに一つの
public
なクラス又はインタフェースの最大数を制限する必要はない。ただし,データベースを使用するシステムは,ファイルに基づいた処理系へとエクスポートするために,Javaプログラムをこの制約に従った形式に変換する方法を提供しなければならない。
CompilationUnit: PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt ImportDeclarations: ImportDeclaration ImportDeclarations別のコンパイル単位で宣言した型は,循環的に相互に依存可能とする。Javaコンパイラは,それらの型すべてを同時にコンパイルするように処理しなければならない。ImportDeclaration TypeDeclarations: TypeDeclaration TypeDeclarations
TypeDeclaration
コンパイル単位(compilation unit) は,次の三つの部分で構成される。ただし,各部分は省略してもよい。
package
宣言(7.4)。コンパイル単位が属するパッケージの完全限定名(6.7)を指定する。
import
宣言(7.5)。他のパッケージの型を単純名を使って参照可能とする。
java.lang
内で宣言したすべての public
な型名を,自動的及び暗黙的にインポートし,それらの型の名前は単純名として使用できる。PackageDeclaration:パッケージ宣言内で用いるパッケージ名は,パッケージの完全限定名(6.7)でなければならない。package
PackageName;
T という名前の型を,完全限定名を P
とするパッケージのコンパイル単位内で宣言していれば,その型の完全限定名は
P.
T とする。そこで,次の例を考える。
package wnj.points; class Point { int x, y; }クラス
Point
の完全限定名は wnj.points.Point
とする。
class FirstCall { public static void main(String[] args) { System.out.println("Mr. Watson, come here. " + "I want you."); } }これは,非常に単純なコンパイル単位を,名前無しパッケージの一部として定義する。
Javaシステムは,少なくとも一つの名前無しパッケージを提供しなければならない。システムは複数の名前無しパッケージを提供してもよいが,これは必要とはしない。各々の名前無しパッケージ内にどのコンパイル単位が存在するかは,ホストシステムが決定する。
パッケージを格納するのに階層型のファイルシステムを使用するJavaシステムでは,名前無しパッケージを各ディレクトリに関連付けることを典型的な方法とする。ある時点で利用可能な名前無しパッケージは一つだけ,つまり“現在の作業ディレクトリ”に関連付けられたパッケージとする。“現在の作業ディレクトリ”の正確な意味は,ホストシステムに依存する。
Javaは名前無しパッケージを,主として,小さな若しくは一時的なアプリケーションの開発時に,又は開発の初期段階に便利なように提供する。
名前無しパッケージを使用するときは注意しなければならない。名前付きパッケージ内のコンパイル単位が,名前無しパッケージから型をインポートすることは可能とするが,このコンパイル単位のコンパイル版は,特定の名前無しパッケージが“カレント”のときしか動かない。この理由から,名前付きパッケージのコンパイル単位では,名前無しパッケージから型を決してインポートしないことが強く望まれる。また,名前無しパッケージ内で宣言した型を名前付きパッケージが偶然にインポートしないように,名前無しパッケージ内の型を
public
として宣言しないことが望ましい。
名前付きパッケージのコンパイル単位が,名前無しパッケージの型をインポートした場合の意図しない結果に対して,Javaシステムが保護手段を提供することが望ましい。それぞれの名前付きパッケージと多くとも一つの名前無しパッケージを関連付ける方法を提供すること,及び一つの名前付きパッケージが複数の名前無しパッケージで使用された場合を検知し警告する方法を提供することを,一つの方法とする。名前付きパッケージの複数のコンパイル版を保持して,複数の名前無しパッケージが一つの名前付きパッケージの使用を処理系が提供することは,特に要求しない。むしろ実際には,避けることが強く望まれる。
java
は常にアクセス可能とすることが望ましく,その標準サブパッケージ
lang
,io
及び util
も常にアクセス可能とすることが望ましい。
Javaプログラムを格納するのに使用するファイルシステム又はデータベースの保護は,コンパイル単位のいずれかが利用可能なときはいつでも,パッケージのすべてのコンパイル単位が利用可能と設定しておくことが強く望まれる。
import
宣言を使用せずに,他のパッケージで宣言した型を参照する唯一の方法は,その完全限定名(6.7)を使用することとする。
ImportDeclaration: SingleTypeImportDeclaration TypeImportOnDemandDeclaration単一の型インポート宣言(7.5.1)は,完全限定名を記述することで一つの型をインポートする。要求時の型インポート宣言(7.5.2)は,名前付きパッケージのすべての
public
な型を必要に応じてインポートする。
import
宣言は,実際に import
宣言を含むコンパイル単位内でだけ,単純名によって型を使用可能とする。限定的に導入する名前の有効範囲は,現在のコンパイル単位の
package
文及び他の import
文,並びに同じパッケージ内の他のコンパイル単位を含まない。説明的な例としては(7.5.4)を参照すること。
SingleTypeImportDeclaration:型名 TypeName は,クラス又はインタフェース型の完全限定名でなければならない。名前付き型が存在しなければ,コンパイル時エラーが発生する。名前付き型が現在のパッケージ内に存在しなければ,アクセス可能(6.6),つまりアクセス可能パッケージ内に存在しimport
TypeName;
public
(8.1.2,9.1.2)宣言されている,となっていなければならない。そうでないときには,コンパイル時エラーが発生する。
import java.util.Vector;この例では,単純名
Vector
は,コンパイル単位内のクラス及びインタフェース宣言内で利用可能とする。そこで,単純名
Vector
は,同じ名前をもつフィールド,
仮引数又は局所変数の宣言によって隠ぺい(6.3)されない,すべての場所でパッケージ
java.util
内の型 Vector
を参照する。
同じコンパイル単位内の二つの単一の型インポート宣言が,同じ単純名をもつ型をインポートしようとすれば,二つの型が同じ型でなければ,コンパイル時エラーが発生する。同じ型の場合は,重複する宣言は無視する。現在のコンパイル単位内で,要求時の型インポート宣言(7.5.2)以外の方法で同じ名前をもつ他の型を宣言すれば,コンパイル時エラーが発生する。
この例は,
import java.util.Vector;
class Vector { Object[] vec; }
Vector
の二重宣言のために,コンパイル時エラーを引き起こす。同様に,次の例もコンパイル時エラーを引き起こす。
この例では,
import java.util.Vector;
import myVector.Vector;
myVector
が次のコンパイル単位を含むパッケージとする。
コンパイラは,完全限定名(6.7)で型を記憶する。単純名及び完全限定名は,両方とも使用可能なときはいつでも交換して使用してもよい。
package myVector;
public class Vector { Object[] vec; }
import
文は,サブパッケージをインポートできず,型だけをインポート可能とする。例えば,次の例に示すように,型
java.util.Random
を参照するために java.util
をインポートし util.Random
という名前を使用しようとしても動作しない。
import java.util; // incorrect: compile-time error
class Test { util.Random generator; }
public
な型を,必要に応じてインポート可能とする。
TypeImportOnDemandDeclaration:ホストシステム(7.2)によって決定される,アクセス不可能(6.6)なパッケージを,要求時の型インポート宣言で名前付けすることは,コンパイル時エラーとする。同じコンパイル単位における二つ以上の要求時の型インポート宣言が,同じパッケージを名前付けしてもよい。その効果は,一つだけ宣言が存在する場合と同じとする。現在のパッケージ又はimport
PackageName. * ;
java.lang
を,要求時の型インポート宣言で名前付けすることは,たとえ既にインポート済みであっても,コンパイル時エラーとはしない。
重複した要求時の型インポート宣言は無視する。
import java.util.*;この例では,コンパイル単位のクラス宣言及びインタフェース宣言において,パッケージ
java.util
で public
と宣言したすべての型の単純名が利用可能となる。そこで,単純名
Vector
は,単純名を Vector
とする型の単一の型インポート宣言,コンパイル単位が属するパッケージ内で
Vector
という名前で宣言した型,又は Vector
という名前のフィールド, 仮引数若しくは局所変数の宣言によって隠ぺい(6.3)されない限り(こうした条件が発生することは普通ではないが),すべての場所でパッケージ
java.util
内の型 Vector
を参照する。
package
文の直後の各コンパイル単位の先頭に,
import java.lang.*;という宣言が,存在するかのように,あらかじめ定義されたパッケージ
java.lang
で宣言した各 public
な型名を自動的にインポートする。
java.lang
の完全な仕様は,20に記述する。java.lang
では,次の public
を型を定義する。
AbstractMethodError LinkageError ArithmeticException Long ArrayStoreException Math Boolean NegativeArraySizeException Character NoClassDefFoundError Class NoSuchFieldError ClassCastException NoSuchMethodError ClassCircularityError NullPointerException ClassFormatError Number ClassLoader NumberFormatException ClassNotFoundException Object CloneNotSupportedException OutOfMemoryError Cloneable Process Compiler Runnable Double Runtime Error RuntimeException Exception SecurityException ExceptionInInitializerError SecurityManager Float StackOverflowError IllegalAccessError String IllegalAccessException StringBuffer IllegalArgumentException System IllegalMonitorStateException Thread IllegalThreadStateException ThreadDeath IncompatibleClassChangeError ThreadGroup IndexOutOfBoundsException Throwable InstantiationError UnknownError InstantiationException UnsatisfiedLinkError Integer VerifyError InternalError VirtualMachineError InterruptedException
Vector
が存在する。それが,Mosquito
という名前の
public
クラスを宣言する。
コンパイル単位は次のとおりとする。
package Vector;
public class Mosquito { int capacity; }
package strange.example;
import java.util.Vector;
import Vector.Mosquito;
class Test { public static void main(String[] args) { System.out.println(new Vector().getClass()); System.out.println(new Mosquito().getClass()); } }パッケージ
java.util
からクラス Vector
をインポートする単一の型インポート宣言(7.5.1)は,パッケージ名 Vector
がそれに続く import
宣言で出現し,正しく認識されることを妨げない。この例はコンパイル可能で,次の出力を生成する。
class java.util.Vector class Vector.Mosquito
TypeDeclaration: ClassDeclaration InterfaceDeclaration;Javaコンパイラは,型宣言のレベルで出現する余計な"
;
"字句を無視しなければならない。Javaは,次のように記述する習慣のあるC++プログラマに対する譲歩として,はぐれたセミコロンを許す。
class date { int month, day, year; };(Javaでは不可能だが,C++では,"
}
"及び";
"の間に変数を宣言するために識別子のコンマで分離したリストを提供することができる。)余計なセミコロンは,新たらしいJavaコードでは使用しないことが望ましい。Javaコードを整形するソフトウェアは,それらを削除することができる。
デフォルトでは,パッケージで宣言した型は,そのパッケージのコンパイル単位内でだけアクセス可能とする。しかし,他のパッケージ(6.6,8.1.2,9.1.2)のコードからその型をアクセス可能とするために,型を
public
として宣言してもよい。
Java処理系は,完全限定名(6.7)でパッケージ内の型を記憶しなければならないB型の名前付けの様々な方法は,その名前が同じ型を参照していることを確認するために,完全限定名に展開しなければならない。例えば,コンパイル単位が次の単一の型インポート宣言を含む (7.5.1)場合を考える。
import java.util.Vector;コンパイル単位内では,単純名
Vector
及び完全限定名
java.util.Vector
は同じ型を参照する。
Javaパッケージがファイルシステム(7.2.1)に格納されるとき,ホストシステムは,次のいずれかが真の場合は,型名及び(.java
又は .jav
のような)拡張子から構成される名前でファイル内にその型を見つけられなければ,コンパイル時エラーとする制約を課すことができる。
この制約は,コンパイル単位ごとにそうした型が高々一つ存在しなければならないことを意味する。この制約によって,Javaコンパイラ及びJava仮想計算機は,パッケージ内で,名前付きクラスを容易に見つけられる。例えば,
public
な型
wet.sprocket.Toad
のソースコードは,ディレクトリ
wet/sprocket
のファイル Toad.java
で見つかり,それに対応するオブジェクトコードは,同じディレクトリ内のファイル
Toad.class
で見つかる。
Javaパッケージがデータベースに格納されるとき(7.2.2),ホストシステムはそうした制約を課す必要はない。
実際には,それが public
かどうか,又は他のコンパイル単位内のコードから参照されているかどうかにかかわらず,多くのJavaプログラマは,それぞれのクラス又はインタフェース型をそれ自体のコンパイル単位に入れている。
一意なパッケージ名を使用していなければ,名前の衝突が生じたどちらかのプログラムを開発してからはるかに時間が経過した時点で,パッケージ名の衝突が生じる可能性がある。この場合,ユーザ又はプログラマにとって,解決が困難又は不可能な状況が生じる。標準のJava仮想計算機環境のクラス
ClassLoader
(20.14)は,同じ名前をもったパッケージを互いから分離するために使用可能で,そのような場合,パッケージが制約された相互動作をもつであろう。しかし,あまり凝っていないJavaプログラムに対して透過的な方法ではない。
一意なパッケージ名を生成するには,まず,Sun.COM
のようなインターネットドメイン名を取得する(あるいは,それをもっている組織に所属する)。
その後,この名前を構成要素ごとに逆にして (例えば,COM.Sun
を行って),パッケージ名の前置詞として使用する。それ以降の名前は,パッケージ名を管理するための組織内で開発された規約を使用する。
そうした規約では,ディレクトリ名の構成要素を,部,課,プロジェクト,マシン又はログイン名に指定するかもしれない。次に例を示す。
COM.Sun.sunsoft.DOE COM.Sun.java.jag.scrabble COM.Apple.quicktime.v2 EDU.cmu.cs.bovik.cheese GOV.whitehouse.socks.mousefinder一意なパッケージ名の最初の構成要素は,常にすべて大文字のASCII文字で書き,現時点では
COM
,EDU
,GOV
,MIL
,NET
又は ORG
という最上位のドメイン名の一つ,又はISO標準3166,1981で規定された英字二文字の国別コードの一つとする。詳細については,ftp://rs.internic.net/rfc
に格納されたドキュメント,例えば,rfc920.txt
及び
rfc1032.txt
を参照のこと。
パッケージの名前は,インターネットにおいてパッケージが格納されている場所についての何らかの情報を示すものではない。例えば,EDU.cmu.cs.bovik.cheese
という名前のパッケージが,インターネットアドレス
cmu.EDU
,cs.cmu.EDU
又は
bovik.cs.cmu.EDU
から必ず入手できるというわけではない。一意なパッケージ名を生成するためのJavaの規約は,Javaパッケージ名のために独自の登録簿を作る代りとして,既存の広く知られた一意な名前の登録簿の上にパッケージ名前付け規約を追加しているだけとする。
新たなインターネットドメイン名を必要とする場合は,ftp://ftp.internic.net
から申込書を入手し,記入後の帳票を電子メールで
domreg@internic.net
宛に提出することができる。現在登録されているドメイン名を見つけるには,rs.internic.net
に telnet
接続して,whois
機能を使用すればよい。