目次 | 前 | 次 | 索引 | Java言語規定 第2版 |
名前は,プログラムで宣言した実体を参照するために使用する。宣言した実体 (6.1) は,パッケージ,クラス型,インタフェース型,参照型のメンバ(クラス,インタフェース,フィールド又は,メソッド),(メソッド,コンストラクタ又は例外ハンドラに対する)仮引数又は局所変数とする。
プログラムにおける名前は,単一の識別子で構成される単純名又は".
"トークンで区切られる識別子の並びから構成される限定名 (6.2)のいずれかとする。
宣言によって導入したすべての名前は, 有効範囲(scope) (6.3)をもつ。有効範囲とは,その中から,宣言した実体が単純名によって参照できるプログラムテキストの一部分とする。
パッケージ及び参照型(つまり,クラス型,インタフェース型及び配列型)は,メンバ(6.4)をもつ。メンバは,限定名 N.
x を使用して参照可能とする。 ここで Nは単純名又は限定名とし,x は識別子とする。N がパッケージに名前付けをしていれば,x はそのパッケージのメンバ,つまり,クラス型,インタフェース型又は下位パッケージのいずれかとする。N が参照型又は参照型の変数に名前付けしていれば,x はその型のメンバ,すなわちフィールド又はメソッドに名前付けする。
名前の意味の決定(6.5)においては,同じ名前をもったパッケージ,型,変数及びメソッドの間のあいまいさを解消するために,名前が出現する文脈を使用する。
アクセス制御(6.6)は,メンバへのアクセス(access)が許可されるときを制御するために,クラス,インタフェース,メソッド又はフィールドの宣言で指定できる。アクセスは,有効範囲とは異なる概念とする。アクセスは,宣言した実体が,限定名,フィールドアクセス式(15.11)又はメソッドを単純名で指定しない場合のメソッド呼出し式(15.12) によって参照できる,プログラムテキストの部分を指定する。 デフォルトアクセスでは,メンバ宣言を含んでいるパッケージ内のどこからでも,そのメンバにアクセスできる。その他には,public
,protected
及び private
がありうる。
完全限定及び正準名(6.7)及び名前付け規約(6.8)についてもこの章で述べる。
フィールド,仮引数又は局所変数の名前は,式(15.14.1)として使用できる。 メソッドの名前は,メソッド呼出し式(15.12)の一部としてだけ式に出現してよい。クラス又はインタフェース型の名前は,クラスリテラル(15.8.2),限定this式(15.8.4),クラスインスタンス生成式(15.9),配列生成式(15.10),キャスト式(15.16),若しくは instanceof
式(15.20.2)の一部分,又はフィールド若しくはメソッドに対する限定名の一部としてだけ式に出現してよい。パッケージの名前は,クラス型又はインタフェース型の限定名の一部としてだけ式に出現してよい。
package
宣言(7.4)で宣言したパッケージ。
abstract
なメソッドの仮引数。
try
文(14.19) の catch
節で宣言した例外ハンドラの仮引数。
名前には,単純名及び限定名の二つの形式が存在する。単純名(simple name) は,単一の識別子とする。限定名(qualified name) は,名前,".
" トークン及び識別子から構成する。
名前の意味の決定 (6.5)においては,名前が出現する文脈を考慮する。規則(6.5)は,どの文脈で,名前が,パッケージ(6.5.3),型(6.5.5),式(6.5.6),又はメソッド(6.5.7) における変数若しくは値を表示(参照)しなければならないかを識別する。
プログラムにおける識別子すべてが,名前の一部になるとは限らない。識別子は,次の状況においても使用する。
.
"トークンの前に出現するキーワードsuper
の値とするオブジェクトのメンバを示すために,".
"トークンの後に識別子が出現してもよい。
.
"トークンの前に出現するキーワード super
の値とするオブジェクトに対して呼び出されたメソッドを示すために,".
"トークンの後及び "(
"トークンの前に識別子が出現してもよい。
break
(14.14) 及び continue
(14.15)文の中のラベル。
識別子class Test { public static void main(String[] args) { Class c = System.out.getClass(); System.out.println(c.toString().length() + args[0].length() + args.length); } }
Test
,main
並びに最初に出現する args
及び c
は名前ではない。これらは,宣言した実体の名前を指定するために使用されている。名前 String
,
Class
, System.out.getClass
,
System.out.println
, c.toString
, args
及び args.length
が例の中に出現している。length の最初の出現は名前とはしない。メソッド呼出し式(15.12)で出現する識別子とする。二番目に出現する length
も名前とはしない。 メソッド呼出し式 (15.12)で出現する識別子とする。
ラベル付き文,並びにそれに関連のある break
及び continue
文で使用する識別子は,宣言で使用する識別子とは完全に区別する。したがって次に示すコードは正しい。
このコードは,クラスclass TestString { char[] value; int offset, count; int indexOf(TestString str, int fromIndex) { char[] v1 = value, v2 = str.value; int max = offset + (count - str.count); int start = offset + ((fromIndex < 0) ? 0 : fromIndex); i: for (int i = start; i <= max; i++) { int n = str.count, j = i, k = str.offset; while (n-- != 0) { if (v1[j++] != v2[k++]) continue i; } return i - offset; } return -1; } }
String
及びそのメソッド indexOf
のある版からもって来た。元の版では,ラベルは test
と呼ばれていた。ラベルを,局所変数 i
と同じ名前をもつように変更しても,i
の宣言の有効範囲においてそのラベルを不明瞭化(6.3.2)しない。識別子 max
も,文ラベルとして使用できた。つまり,ラベルは,ラベル付き文内の局所変数 max
を隠ぺいしない。各構成要素の有効範囲規則は,その構成要素について記述する節で与える。便宜上,それらの規則をここで繰り返して述べる。
観察可能な(7.4.3)最上位パッケージの宣言の有効範囲は,すべての観察可能コンパイルユニット(7.3)とする。観察可能でないパッケージの宣言は,有効範囲に入らない。下位パッケージの宣言は,有効範囲に入らない。
単一の型インポート宣言 (7.5.1) 又は要求時の型インポート宣言(7.5.2) によってインポートした型の有効範囲は,そのインポート宣言が出現するコンパイル単位におけるすべてのクラス及びインタフェース型宣言(7.6)とする。
最上位型の有効範囲は,その最上位型が宣言されているパッケージにおけるすべての型宣言とする。
ラベル文によって宣言されたラベルの有効範囲は,そのラベル文で直接取り囲まれた文とする。
クラス型Cにおいて宣言又は継承したメンバ宣言の有効範囲は,入れ子になった型宣言を含めて,C本体の全体とする。
インタフェース型I において宣言又は継承したメンバ宣言の有効範囲は,入れ子になった型宣言を含めて,I 本体の全体とする。
メソッド(8.4.1)又はコンストラクタ(8.8.1)の仮引数の有効範囲は,そのメソッド又はコンストラクタの本体の全体とする。
ブロック(14.4.2)における局所変数宣言の有効範囲は,宣言が出現したブロックの残りの部分とする。これは,それ自体の初期化子(14.4)で始まり,その局所変数の宣言文中で,さらに右側に続く宣言子を含む。
ブロックで宣言された局所クラスの有効範囲は,直ちに取り囲むブロックの残りとする。これは,それ自身のクラス宣言を含む。
for
文 (14.13) の ForInit 部において宣言した局所変数の有効範囲は,次のすべてを含む。
for
文の ForInit 部内の,それ自体の右側に続くすべての宣言子。
for
文の 式(Expression) 及び ForUpdate 部。
try
文 (14.19) のcatch
節で宣言した例外ハンドラの仮引数の有効範囲は,catch
と関連するブロックの全体とする。これらの規則は,クラス及びインタフェース型の宣言が,型の使用前に出現する必要がないことを示唆している。
クラスpackage points; class Point { int x, y; PointList list; Point next; } class PointList { Point first; }
Point
の PointList
の使用は正しい。これはクラス型の名前PointList
の有効範囲が,パッケージ points
の他のコンパイル単位 における他の型宣言でも同様に,クラス Point
及びクラス PointList
の両方を含むからとする。名前n の型宣言d は,d が出現した時点ならびにd の有効範囲にある他のすべての名前n の型宣言をおおい隠す。
名前nのフィールド,局所変数,メソッド仮引数,コンストラクタ仮引数,又は例外ハンドラ仮引数の宣言d は,d が出現した時点ならびにd の有効範囲にある他のすべての名前n のフィールド,局所変数,メソッド仮引数,コンストラクタ仮引数,又は例外ハンドラ仮引数の宣言をおおい隠す。
名前n のラベルの宣言d は,d が出現した時点ならびにd の有効範囲にある他のすべての名前n のラベルの宣言をおおい隠す。
名前n のメソッド宣言d は,d が出現した時点ならびにd の有効範囲にある他のすべての名前n のメソッド宣言をおおい隠す。
名前n の型を輸入するパッケージp のコンパイル単位c の単一の型インポート宣言d は,c の中の次の宣言をおおい隠す。
要求時の型インポート宣言は,他のどのような宣言もおおい隠さない。
宣言d がプログラム中の時点p で可視(visible)であるための条件は,d の有効範囲がpを含み,かつ,p での他の宣言によってd がおおい隠されないこととする。文脈から論じているプログラム時点が明白な場合には,単に宣言が可視であるという。
このおおい隠すことが隠ぺい(8.3, 8.4.6.2, 8.5, 9.3, 9.5)とは,異なることに注意。本規定において定義された技術的意味での隠ぺいは,下位クラスでの宣言という理由ではなく,さもなくば継承されたであろうメンバにのみ適用される。おおい隠すことは,また不明瞭化(6.3.2)とも異なる。
次に,局所変数によりフィールド宣言のおおい隠された例を示す。
これは次を出力する。class Test { static int x = 1; public static void main(String[] args) { int x = 0; System.out.print("x=" + x); System.out.println(", Test.x=" + Test.x); } }
この例は,次のものを宣言している。x=0, Test.x=1
Test
。
static
) 変数 x
。これはクラスTest
のメンバとする。
main
。これはクラス Test
のメンバとする。
main
の仮引数 args
。
main
の局所変数x
。
x
はメソッド main
の本体の全体を通して普通に利用できる。しかし,この例では,局所変数 x
の宣言によって,クラス変数 x
はメソッド main
の本体内でおおい隠される。
局所変数は,宣言(14.4.2)されたブロックの残りの部分を有効範囲とする。この例の場合,これはメソッド main
の本体の残りの部分,つまり,初期化子"0
" 並びに print
及び println
の呼出しの部分とする。
print
の呼出しにおける式"x
"は局所変数 x
の値を参照(表示)する。
println
の呼出しは限定名(6.6) Test.x
を使用する。これは,クラス型名Test
を用いて,クラス変数x
にアクセスする。Test.x
の宣言はこの時点ではおおい隠され,単純名で参照できないからである。
これはコンパイルされ、次を出力する。import java.util.*; class Vector { int val[] = { 1 , 2 }; }class Test { public static void main(String[] args) { Vector v = new Vector(); System.out.println(v.val[0]); } }
ここで宣言したクラス1
Vector
は,要求時にインポートするかもしれないクラス java.util.Vector
よりも優先して使用される。不明瞭化は,おおい隠されること(6.3.1) とは異なり,かつ,隠ぺい(8.3, 8.4.6.2, 8.5, 9.3, 9.5)とも異なる。6.8の名前規約は,不明瞭さを減少させるのに役立つ。
6.4では,限定名の議論及び名前の意味の決定についての背景として,パッケージ及び参照型のメンバの概要を示す。メンバの完全な説明については,7.1, 8.2, 9.2, 及び 10.7を参照のこと。
パッケージのメンバは,下位パッケージ又はそのパッケージのすべてのコンパイル単位(7.3) で宣言された最上位(7.6)クラス型(8.)若しくは最上位インタフェース(9.) 型とする。
一般に,あるパッケージの下位パッケージは,ホストシステム(7.2)によって決定される。しかし,パッケージ java
は,常に 下位パッケージlang
及びio
を含み,さらに,その他の下位パッケージを含んでもよい。同じパッケージの二つの異なるメンバは,同じ単純名(7.1)をもってはならない。しかし異なるパッケージのメンバは,同じ単純名をもってもよい。
これは標準パッケージpackage vector; public class Vector { Object[] vec; }
java.util
が,Vector
という名前のクラスを宣言しているのにもかかわらず,Vector
という名前のpublic
クラスをメンバとしてもつ。これら二つのクラス型は,これらが異なる完全限定名(6.7)をもつ事実によって分かるように,異なっている。この例の Vector
の完全限定名は vector.Vector
とする。これに対して java.util.Vector
が,標準クラス Vector
の完全な限定名である。パッケージ vector
は Vector
という名前のクラスを含むので,Vector
という名前の下位パッケージをもつことはできない。Object
は直接的上位クラスをもたない)。
同じ単純名をもつクラス型のフィールド及びメソッドに対する制限は存在しない。同様に,そのクラス型のフィールド又はメソッドとして同じ単純型を持つクラス型のメンバクラス又はメンバインタフェースに対しては何の制限もない。
異なるインタフェースで宣言され継承されるならば,クラスは同じ名前で二つ以上のフィールドをもってよい。そのフィールドを単純名で参照しようとすると,コンパイル時エラーを生じる(6.5.7.2, 8.2)。
次に例を示す。
メソッドinterface Colors { int WHITE = 0, BLACK = 1; } interface Separates { int CYAN = 0, MAGENTA = 1, YELLOW = 2, BLACK = 3; } class Test implements Colors, Separates { public static void main(String[] args) { System.out.println(BLACK); // compile-time error: ambiguous } }
main
内の名前BLACK
はあいまいである。 クラス Test
は,BLACK
という名前の二つのメンバ,Colors
から継承されたもの及び Separates
から継承されたもの,をもつからである。クラス型は,メソッドが異なるシグネチャ(8.4.2)をもてば,つまり,仮引数の数が違うか,又は少なくとも一つの仮引数の型が違うならば,同じ単純名で二つ以上のメソッドをもってもよい。このようなメソッドのメンバ名は, オーバロードされる(overloaded) という。
クラス型は,上位クラス又は上位インタフェースから別途継承され得るメソッドと同じ名前及び同じシグネチャをもつメソッドの宣言を含んでいてもよい。この場合,その上位クラス又は上位インタフェースのメソッドは,継承されない。継承されないメソッドが abstract
であれば,新しい宣言はそれを 実装(implement)するという。継承されないメソッドが abstract
でなければ,新しい宣言はそれを 上書き(override) するという。
クラスclass Point { float x, y; void move(int dx, int dy) { x += dx; y += dy; } void move(float dx, float dy) { x += dx; y += dy; } public String toString() { return "("+x+","+y+")"; } }
Point
は,同じ名前 move
をもつメソッドを二つもつ。特定のメソッド呼出しで選択されるクラス Point
のオーバロードされたメソッドmove
は,15.12で与えられたオーバロード解決手順によってコンパイル時に決定される。
この例では,クラス Point
のメンバは,Point
で宣言された float
インスタンス変数 x
及びy
,二つの宣言されたメソッド move
,宣言されたメソッド toString
,並びにメソッド hashCode
のような Point
がその暗黙の直接的上位クラス Object
(4.3.2) から継承するメンバとする。Point
はクラス Object
のメソッド toString
を継承していないことに注意すること。これは,そのメソッドがクラス Point
内のメソッド toString
の宣言によって上書きされているからである。
throws
節t を持つ。これは,Object
で宣言されたシグネチャs,返却時の型r,throws
節t を持つpublicインスタンスメソッドmに対応する。ただし,同じシグネチャ,同じ返却時の型,適合throws
節を持つメソッドは,インタフェースで明示的に宣言されるとする。
インタフェースinterface Colors { int WHITE = 0, BLACK = 1; } interface Separates { int CYAN = 0, MAGENTA = 1, YELLOW = 2, BLACK = 3; } interface ColorsAndSeparates extends Colors, Separates { int DEFAULT = BLACK; // compile-time error: ambiguous }
ColorsAndSeparates
のメンバは,Colors
から継承したメンバ及びSeparates
から継承したメンバ,つまり,WHITE
, BLACK
(二つの内の最初),CYAN
,
MAGENTA
, YELLOW
,及び BLACK
(二つの内の二番目)を含む。メンバ名 BLACK
はインタフェース ColorsAndSeparates
ではあいまいとする。
public
final
フィールドであるフィールド length
。配列の構成要素の数を含む。(length
は,正又はゼロとする。)
public
メソッド clone
。これは,クラスObject
の同じ名前のメソッドを上書きし,検査例外を投げない。
Object
から継承した全メンバ。clone
メソッドが,継承されない唯一のObject
メソッドとなる。
これは次の出力を生成する。class Test { public static void main(String[] args) { int[] ia = new int[3]; int[] ib = new int[6]; System.out.println(ia.getClass() == ib.getClass()); System.out.println("ia has length=" + ia.length); } }
この例は,クラスtrue ia has length=3
Object
から継承したメソッド getClass
及びフィールドlength
を使用する。最初の println
におけるオブジェクトClass
の比較結果は,構成要素を型int
とするすべての配列が同じ配列型int[]
のインスタンスであることを示す。
PackageName: Identifier PackageName . Identifier TypeName: Identifier PackageOrTypeName . Identifier ExpressionName: Identifier AmbiguousName . Identifier MethodName: Identifier AmbiguousName . Identifier PackageOrTypeName: Identifier PackageOrTypeName . Identifier AmbiguousName: Identifier AmbiguousName . Identifier文脈の使用は,異なる種類の実体間の名前の衝突を最小にすることを助ける。6.8 で説明される名前付け規約に従っていれば,このような衝突が発生することはほとんどない。それにもかかわらず,名前の衝突は,違うプログラマ又は違う組織での開発の進展の典型として,故意ではなく発生することがある。たとえば,型,メソッド及びフィールドが同じ名前をもつことがある。使用文脈から,メソッドが意図されているかどうかは明らかになるため,同じ名前をもつメソッドとフィールドの間の識別は,常に可能となる。
.
"の左側。
extends
節(8.1.3) 内。
implements
節(8.1.4) 内。
extends
節(9.1.2) 内。
try
文の catch
節(14.19) 内の例外仮引数の型。
this
式(15.8.4)の限定型。
super
を用いたフィールドアクセスの限定型(15.11.2) 。
super
を用いたメソッド呼出しの限定型
(15.12)。
instanceof
関係演算子(15.20.2) に続く型。
(
"の前。
.
"及びIdentifier から構成される限定名ならば,".
" の左側の名前を最初に再分類する。その理由は,それ自体がAmbiguousNameだからである。このときには,次の選択が存在する。
.
"の左側の名前をPackageName として再分類したとき,".
"の左側の名前のパッケージが存在し,そのパッケ−ジがそのIdentifier と同じ名前の型の宣言を含んでいれば,このAmbiguousNameは,TypeNameとして再分類する。そうでなければ,この AmbiguousNameは,PackageNameとして再分類する。その名前のパッケージが実際に存在するかどうかは,その後の段階で決定する。
.
"の左側の名前をTypeNameとして再分類したとき,その識別子が,この型名で表記されるクラス又はインタフェースのメソッド又はフィールドの名前ならば,このAmbiguousNameは,ExpressionNameとして再分類する。そうでなければ,もし,その識別子が,その型名で表記されるクラス又はインタフェースのメンバ型の名前ならば,このあいまい名は型名として再分類される。そうでなければ,コンパイル時エラーが生じる。
.
"の左側の名前をExpressionName として再分類したとき,Tをこの式名で表記される式の型とする。識別子がTで表記されるクラス又はインタフェースのメソッド又はフィールドの名前ならば,このAmbiguousNameは,ExpressionNameとして再分類する。そうでなければ,識別子がTで表記されるクラス又はインタフェースのメンバ型(8.5, 9.5) の名前ならば,このあいまい名は型名として再分類される。そうでなければ,結果はコンパイル時エラーとする。
例として,次のとおり設計された"library code"を考える。
さらに,他のパッケージ内での次の例を考える。package org.rpgpoet; import java.util.Random; interface Music { Random[] wizards = new Random[4]; }
まず最初に,名前package bazola; class Gabriel { static int n = org.rpgpoet.Music.wizards.length; }
org.rpgpoet.Music.wizards.length
は, ExpressionName として分類する。その理由は,それはPostfixExpression として機能するからである。したがって,次の各名前,は,最初は AmbiguousName として分類する。これらはその後再分類する。org.rpgpoet.Music.wizards org.rpgpoet.Music org.rpgpoet org
org
という名前の変数又は型が存在しないので)単純名 org
は,PackageNameとして再分類する。
org
のコンパイル単位で rpgpoet
という名前のクラス又はインタフェースがないと仮定すると(パッケージ org
は rpgpoet
という名前の下位パッケージをもつのでそのようなクラスやインタフェースがないことは判っている),限定名 org.rpgpoet
は,PackageNameとして再分類する。
org.rpgpoet
は,Music
という名前のインタフェース型をもつので,限定名 org.rpgpoet.Music
は,TypeNameとして再分類する。
org.rpgpoet.Music
は,TypeName なので,限定名org.rpgpoet.Music.wizards
は,ExpressionNameとして再分類する。
.
Id ならば,Q もパッケージ名でなければならない。パッケージ名 Q.
Id は, Q という名前のパッケージ内の,Id という名前のメンバのパッケージに名前付けする。Qが観察可能なパッケージ(7.4.3)を名前付けしないか,又は Id がそのパッケージの観察可能な下位パッケージの単純名でなければ,コンパイル時エラーが発生する。そうでなければ,その PackageOrTypeNameはPackageName として再分類される。その PackageOrTypeNameの意味は,再分類された名前の意味とする。
そうでなければ, PackageNameとして再分類される。 限定PackageOrTypeNameの意味は,再分類名の意味とする。
識別子は,その名前をもつ複数の型の有効範囲内に出現可能とする 。この場合,その名前が表す型は,次のとおり決定する。
.
Id ならば,Q は型名又はパッケージ名でなければなら ない。Id が,名前がQ で表される型又はパッケージのメンバである正確に一つの型の名前であるなら,限定型名は,その型を表す。Id がQ 内のメンバ型(8.5, 9.5) の名前でないか,Q内のメンバ型名Id がアクセス可能(6.6)でないか,Id がQ 内の複数のメンバ型の名前ならば ,コンパイル時エラーが発生する。 これは,最初の実行時に次の出力を生成した。package wnj.test; class Test { public static void main(String[] args) { java.util.Date date = new java.util.Date(System.currentTimeMillis()); System.out.println(date.toLocaleString()); } }
この例では,名前Sun Jan 21 22:56:29 1996
java.util.Date
は,型を表していなければならない。そこでまず最初に,java.util
がアクセス可能な型又はパッケージであるかどうかを決めるために,その手順を再帰的に使用し,実際アクセス可能なので,次に,型Date
がこのパッケージ内でアクセス可能かどうかを確認する。
final
(8.3.1.2)と宣言されていれば,その式名はそのフィールドの値を表す。その式名の型は,そのフィールドの宣言された型とする。そのIdentifierが値でなく変数を要求する文脈に出現すれば,コンパイル時エラーが発生する。
static
メソッド(8.4.3.2),静的初期化子(8.7)又は static
変数の初期化子(8.3.1.1, 12.4.2)内に出現すれば,コンパイル時エラーが発生する。
class Test { static int v; static final int f = 3; public static void main(String[] args) { int i; i = 1; v = 2; f = 33; // compile-time error System.out.println(i + " " + v + " " + f); } }
i
, v
及びf
への代入の左辺で使用している名前は,局所変数 i
,フィールド v
及びf
の値(変数f
ではない。その理由は,f
がfinal
変数だからとする。)を表す。したがって,最後の代入の左辺が変数で はないために,この例はコンパイル時エラーを生じる。エラーとなる代入を削除すれば,修正したコードはコンパイルでき,次の結果を出力する。
1 2 3
.
Idならば,Q は既に,パッケージ名,型名又は式名として分類されている。
static
と宣言されていなければ),コ ンパイル時エラーが発生する。
final
宣言されていれば,Q.
Idはそのクラス変数の値を表す。式Q.
Idの型は,そのクラス変数を宣言した型とする。Q.
Idが値ではなく変数を要求する文脈内に出現すれば,コンパイル時エラーが発生する。
.
Idはクラス変数を表す。式 Q.
Idの型は,クラス変数を宣言した型とする。
.
Idは,そのフィールドの値を表す。式 Q.
Idの型は,そのフィールドの宣言された型とする。Q.
Idが,値ではなく変数を要求する文脈内に出現すれば,コンパイル時エラーが発生する。
final
フィールド(クラス変数又はインスタンス変数のいずれであってもよい)。
final
フィ−ルドlength
。
.
Idは,フィールドの値を表す。式 Q.
Idの型 はそのフィールドを宣言した型とする。Q.
Idが値ではなく変数を要求する文脈内に出現すれば,コンパイル時エラーが発生する。
.
Idは,変数,つまり,クラスTのフィールドId を表す。これは,クラス変数又はインスタンス変数のいずれであってもよい。 式 Q.
Idの型はそのフィールドを宣言した型とする。
次に例を示す。
二つのコンパイル時エラーが生じる。これはclass Point { int x, y; static int nPoints; } class Test { public static void main(String[] args) { int i = 0; i.x++; // compile-time error Point p = new Point(); p.nPoints(); // compile-time error } }
int
変数 i
がメンバをもたないこと,及びnPoints
がクラス Point
のメソッドでないこと のためである。.
Id ならば,Qは,パッケージ名,型名又は式名 として既に分類されている。Qがパッケージ名ならば,コンパイル時 エラーが発生する。そうでなければ,Id はメソッド呼出しのために使用するメソッド名とする。Qが型名ならば,Id は型 Qの static
メソッドを少なくとも一つ名前付けしなければならない。Qが式名ならば,T を式 Qの型とする。Id は型 T のメソッドを少なくとも一つ名前付けしなければならない。メソッド呼出し式における限定メソッド名の解釈の詳細な解説は15.12を参照のこと。
アクセス可能性は,コンパイル時に決定可能な静的特性であることに注意せよ。それは,型及び宣言修飾子にのみ依存する。限定名は,パッケージ及び参照型のメンバへのアクセスの方法とする。関係するアクセスの方法は,フィールドアクセス式(15.11) 及びメソッド呼出し式 (15.12)を含む。三つのすべては,パッケージ,型又は型をもつ式の指示が先行し,".
" が出現し,パッケージ又は型のメンバを名前付けするIdentifier が続くという点で構文的に類似する。これらは,まとめて限定アクセス(qualified access) のための構文要素として知られる。
アクセス制御は,限定アクセス並びにクラスインスタンス生成式 (15.9)及び明示的なコンストラクタ呼出し (8.8.5)に適用する。アク セス可能性は,隠ぺい及びメソッド上書き(8.4.6.1)を含めて,クラスメンバの継承(8.2)にも影響する。
public
宣言していれば,その宣言のコンパイル単位(7.3)が可視ならば,任意のコードによってアクセス可能とする。最上位クラス又はインタフェース型を public
宣言していなければ,それを宣言しているパッケージ内からだけアクセス可能とする。
public
宣言していれば,アクセスは許可される。インタフェースのすべてのメンバは,暗黙的に public
とする。
protected
宣言していれば,次のいずれか一つが真のときにだけ,アクセスは許可される。
protected
メンバを宣言しているクラスを含むパッケージ内から発生している。
private
宣言していれば,アクセス許可の必要十分条件を,メンバの宣言を取り囲む最上位クラス(7.6) の本体内から発生していることとする。
protected
アクセスの詳細protected
メンバ又はコンストラクタは,そのオブジェクトの実装に対して責任があるコードによってだけ,それを宣言したパッケージの外部からアクセスしてよい。protected
メンバへのアクセスprotected
メンバmを宣言しているクラスとする。Cの下位クラスS の本体内からのみアクセスが許される。さらに,Id をインスタンスフィールド又はインスタンスメソッドの表記とした場合,次のとおりとする。
.
Id,ここで Q は ExpressionNameとする,によってならば,アクセス許可の必要十分条件を,式Q の型が S又は Sの下位クラスの場合とする。
.
Id又はメソッド呼出し式 E.
Id(
. . .)
によってならば,アクセス許可の必要十分条件を,Eの型が S 又は S の下位クラスとする。
protected
コンストラクタへの限定アクセスprotected
コンストラクタを宣言しているクラスとし,Sをその中の宣言でprotected
コンストラクタが出現する最内クラスとする。この場合に次となる。
super(
. . .)
の又はEを 基本(Primary) 式とするE.super(. . .)
の上位クラスコンストラクタ呼出しによる場合は,アクセスは許可される。
new
C(. . .){...}
の匿名クラスインスタンス生成式 又はEを基本(Primary)式とするE.new C(. . .){...}
の限定クラスインスタンス生成式によってならば,アクセスは許可される。
new
C(
. . .)
の単純クラスインスタンス生成式 又はE を 基本(Primary)式とするE.new C(. . .)
の限定クラスインスタンス生成式によってならば,アクセスは許可されない。protected
コンストラクタは,それが定義されているパッケージ内からだけ,(匿名クラスを宣言しない)クラスインスタンス生成式によってアクセス可能とする。
及びpackage points; class PointVec { Point[] vec; }
パッケージpackage points; public class Point { protected int x, y; public void move(int dx, int dy) { x += dx; y += dy; } public int getX() { return x; } public int getY() { return y; } }
points
内では,二つのクラス型を宣言する。
PointVec
は public
ではなく,パッケージ points
のpublic
インタフェースの一部でもないが,そのパッケージ内の他のクラスによってだけ使用できる。
Point
は public
宣言されていて,他のパッケージで使用できる。それは,パッケージ points
の public
インタフェースの一部とする。
Point
の メソッド move
, getX
及び getY
は public
宣言されており,そのため,型Point
のオブジェクトを使用するすべてのコードで利用できる。
x
及び y
は protected
宣言されていて,パッケージ points
の外からは,クラスPoint
の下位クラス内でだけ,かつ,それらをアクセスするコードによって実装されているオブジェクトのフィールドであるときだけ使用できる。
protected
アクセス修飾子がアクセスを制限する方法の例については6.6.7を参照のこと。public
及び非public
クラスへのアクセスの例public
をもたなければ,そのクラス宣言へのアクセスは,それを宣言したパッケージに制限される(6.6)。
二つのクラスがコンパイル単位内で宣言されている。クラスpackage points; public class Point { public int x, y; public void move(int dx, int dy) { x += dx; y += dy; } } class PointList { Point next, prev; }
Point
はパッケージ points
の外で使用できる。一方,クラス PointList
はパッケージ内でだけ使用できる。
したがって,他のパッケージ内のコンパイル単位は,points.Point
を,次の二つの方法でアクセスできる。
まず,完全限定名を使用する例を次に示す。
さらに,完全限定名を記述する単一の型インポート宣言(7.5.1)を使用し,その結果,それ以降単純名が使用できる例を次に示す。package pointsUser; class Test { public static void main(String[] args) { points.Point p = new points.Point(); System.out.println(p.x + " " + p.y); } }
しかし,このコンパイル単位は,package pointsUser; import points.Point; class Test { public static void main(String[] args) { Point p = new Point(); System.out.println(p.x + " " + p.y); } }
points.PointList
を使用又はインポートできない。これは public
宣言をしていないので,パッケージpoints
の外からはアクセス可能ではないからである。public
,
protected
又はprivate
をいずれも指定していなければ,クラスメンバ又はコンストラクタは,そのクラスメンバを宣言しているクラスの宣言を含むパッケージの全体からアクセス可能とする。しかし,そのクラスメンバ又はコンストラクタは,他のパッケージからはアクセス不能とする。
public
クラスが,デフォルトアクセスのメソッド又はコンストラクタをもてば,このメソッド又はコンストラクタは,このパッケージの外で宣言した下位クラスによってアクセス又は継承されることはない。
次に例を示す。
他のパッケージ内の下位クラスは同じシグネチャ(8.3.2)及び返却値の型をもつ関連のないメソッドpackage points; public class Point { public int x, y; void move(int dx, int dy) { x += dx; y += dy; } public void moveAlso(int dx, int dy) { move(dx, dy); } }
move
を宣言してよい。元のメソッド move
はパッケージ morepoints
からアクセスできないので,super
を使用してはならない。
package morepoints; public class PlusPoint extends points.Point { public void move(int dx, int dy) { super.move(dx, dy); // compile-time error moveAlso(dx, dy); } }
Point
の move が PlusPoint
内のmove
によって上書きされないため,Point
内のメソッド moveAlso
は PlusPoint
内のメソッド move を呼ぶことは決してない。
したがって,PlusPoint
からsuper.move
を削除してテストプログラムを実行すれば,正常に終了する。
import points.Point; import morepoints.PlusPoint; class Test { public static void main(String[] args) { PlusPoint pp = new PlusPoint(); pp.move(1, 1); } }
Point
の move
が PlusPoint
内の move によって上書きされれば,このプログラムは,StackoverflowError
が発生するまで無限に再帰するであろう。public
フィールド,メソッド及びコンストラクタの例public
クラスのメンバ又はコンストラクタは,それを宣言しているパッケージの全体から,及びそれを宣言している他のパッケージが可視(7.4.3)ならば,そのパッケージから,アクセス可能とする。例えば,次のコンパイル単位を考える。
package points; public class Point { int x, y; public void move(int dx, int dy) { x += dx; y += dy; moves++; } public static int moves = 0; }
public
クラスPoint
は,メソッドmove
及びフィールドmoves
をpublic
メンバとしてもつ。これらのpublic
メンバは,パッケージ points
にアクセスする他の任意のパッケージに対してアクセス可能とする。フィールドx
及びy
はpublic
ではなく,パッケージpoints
内からでだけアクセス可能とする。protected
フィールド,メソッド及びコンストラクタの例 points
を宣言する次の例を考える。
さらに,パッケージpackage points; public class Point { protected int x, y; void warp(threePoint.Point3d a) { if (a.z > 0) // compile-time error: cannot access a.z a.delta(this); } }
threePoint
を次のとおり宣言する。
これは,クラスpackage threePoint; import points.Point; public class Point3d extends Point { protected int z; public void delta(Point p) { p.x += this.x; // compile-time error: cannot access p.x p.y += this.y; // compile-time error: cannot access p.y } public void delta3d(Point3d q) { q.x += this.x; q.y += this.y; q.z += this.z; } }
Point3d
を定義する。このメソッドdelta
で,コンパイル時エラーが発生する。つまり,仮引数 p
の protected メンバx
及びy
にはアクセスできない。その理由は,Point3d
(フィールドx
及びy
への参照が発生するクラス)は,Point
(x
及びy
を宣言するクラス)の下位クラスだが,これは,Point
(仮引数p
の型)の実装には含まれないためである。メソッドdelta3d
は,仮引数q
の protected メンバにアクセス可能とする。その理由は,クラスPoint3d
は,Point
の下位クラスであって,Point3d
の実装に含まれるからである。
メソッド delta
は,その仮引数をPoint3d
とするキャスト(5.5, 15.16) を試みることはできるが,実行時の p
のクラスがPoint3d
でなければ,このキャストは失敗し,例外を発生する。
メソッド warp でもコンパイル時エラーが発生する。仮引数a
の protected メンバz
にアクセスできない。その理由は,クラス Point(フィールド z
への参照が発生するクラス)は,Point
(仮引数a
の型)の実装に関連しているが,Point3d
(z
を宣言したクラス)の下位クラスでないからである。
private
フィールド,メソッド及びコンストラクタの例private
クラスのメンバ又はコンストラクタは,それを宣言したクラス本体の中だけでアクセスでき,下位クラスによって継承されない。次に例を示す。
class Point { Point() { setMasterID(); } int x, y; private int ID; private static int masterID = 0; private void setMasterID() { ID = masterID++; } }
private
メンバ,ID,
masterID
及びsetMasterID
は,クラ スPoint
の本体内でだけ使用可能となる。これらは,Point
宣言の本体の外側では,限定名,フィールドアクセス式又はメソッド呼出し式によってアクセスできない。
private
コンストラクタの使用例は,8.8.8を参照のこと。
boolean
, char
,
byte
, short
, int
, long
,
float
, 又は double
とする。
.
"を続け,さらに,その下位パッケージの単純(メンバ)名を続けたものから構成する。
.
"を続け,さらに,そのクラス又はインタフェースの単純名を続けたものから構成する。
[]
"を続けたもので構成する。
long
の完全限定名は"long
"とする。
java.lang
の完全限定名は"java.lang
"とする 。その理由は,パッケージjava
の下位パッケージlang
だからとなる。
java.lang
で定義したクラスObject
の完全限定名は,"java.lang.Object
"とする。
java.util
で定義したインタフェース Enumeration
の完全限定名は,"java.util.Enumeration
"とする。
double
の配列"の完全限定名は,"double[]
"とする。
String
の配列の配列の配列の配列"の完全限定名は, "java.lang.String[][][][]
"とする。
型package points; class Point { int x, y; } class PointVec { Point[] vec; }
Point
の完全限定名は"points.Point
",型PointVec
の 完全限定名は"points.PointVec
"及びクラスPointVec
のvec
フィールドの型の完全限定名は"points.Point[]
"とする。
すべてのパッケージ,最上位クラス,最上位インタフェース及びプリミティブ型は,正準名を持つ。配列型が正準名を持つ必要十分条件は,その要素型が正準名を持つこととする。 他のクラスCのメンバクラス又はメンバインタフェース M が正準名を持つ必要十分条件は,C が正準名を持つこととする。この場合,M の正準名は,C の正準名, ".",M の単純名の連なったものとする。すべてのパッケージ,最上位クラス,最上位インタフェース及びプリミティブ型は,正準名を完全限定名と同じとする。配列型の正準名は,配列の要素型が正準名を持つ場合に限り定義される。この場合,配列型の正準名は,配列型の構成要素の型の正準名に"[]
"を続けたもので構成する。
この例で,package p; class O1 { class I{}} class O2 extends O1{};
p.O1.I
及び p.O2.I
は共に同じクラスを表す完全限定名となる。しかし,p.O1.I
だけが正準名となる。
すべてのJavaプログラムで,以下の規約を使用することが望ましい。しかし,長期間にわたり使用してきた,慣用的な使用法が本規約と異なるならば,本規約に,無条件に従う必要はない。例えば,クラス v のメソッド sin
及びメソッド cos
は,短く,動詞ではないという理由でJavaの規約を守っていないが,数学の規約に従う。
com
,
edu
, gov
, mil
, net
,
org
のようなインターネットドメインを示す2文字又は3文字の小文字,又は uk
若しくは jp
のような2文字のISO国名コードで構成する限定名とする。この規約にしたがって作成した架空の一意な名前の例を次に示す。
局所使用だけを意図したパッケージの名前は,小文字で始まる識別子をもつことが望ましい。しかし,その最初の識別子をcom.JavaSoft.jag.Oak org.npr.pledge.driver uk.ac.city.rugby.game
java
とするのは望ましくない。識別子 java
で始まるパッケージ名は,Javaプラットフォームパッケージを名前付けするためにSunが予約している。
式にパッケージ名が出現するときは,次のとおりとする。
import
宣言(7.5)を使用することを可能とする。
パッケージ名の最初の構成要素を,型名と間違えることは通常はあまりない。これは型名は,普通1文字の大文字で始まるからである。(Java言語は,実際には,名前がパッケージ 名又は型名を決定するために大文字及び小文字の違いには依存しない。)
同様に,インタフェース型の名前は,各単語の先頭文字を大文字とし,大文字及び小文字を混在させ,短く,記述的で過度に長くないことが望ましい。その名前は,記述的な名詞又は名詞句であってよい。これは,インタフェースClassLoader
SecurityManager
Thread
Dictionary
BufferedInputStream
java.io.DataInput
及びjava.io.DataOutput
のように,インタフェースを,抽象上位クラスであるかのように使用するときに適している。名前は,インタフェースRunnable
及びCloneable
のように,振る舞いを記述する形容詞としてもよい。
クラス及びインタフェース型の名前を不明瞭化することはほとんどない。規約により,フィールド,仮引数及び局所変数の名前は小文字で始まるのに対して,型名は大文字で始まるので,普通は,型名を隠ぺいしない。
get
)及び設定する(set
)メソッドは,get
V及びset
Vという名前とすることが望ましい。クラスThread
のメソッドgetPriority
及びメソッドsetPriority
をこの例とする。
String
のように,length
という名前にすることが望ましい。
boolean
条件を検査するメソッドは,is
Vという名前とすることが望ましい。クラスThread
のメソッド isInterrupted
をこの例とする。
to
Fという名前とすることが望ましい。クラスObject
のメソッド toString
,及びクラスjava.util.Date
のメソッドtoLocaleString
及びtoGMTString
をこの例とする。
メソッド名は,他の名前を不明瞭化したり,他の名前で不明瞭化できない(6.5.7)。
final
でないフィールドの名前は,先頭文字は小文字で始まり,それに続く単語の先頭文字を大文字とすることが望ましい。適切に設計されたJavaクラスは,定数のフィールド(final
static
フィールド) (6.8.5)を除くと,public
又はprotected
フィールドは非常に少ないことに注意すること。
フィールドは,名詞,名詞句又は名詞の省略形の名前をもつことが望ましい。この規約の例としては,クラスjava.io.ByteArrayInputStream
のフィールドbuf
, pos
及びcount
並びにクラス java.io.InterruptedIOException
のフィールドbytesTransferred
がある。
フィールド名を含む不明瞭化はほとんどない。
import
宣言(7.5)を使用することができる。
_
"で区切られた構成要素をもつ,すべて大文字の,一つ以上の単語 ,頭文字又は略語の並びとすることが望ましい。クラス型のfinal
変数も,慣例として,同じ並びとしてよい。定数名は,記述的であって,不必要に省略しないことが望ましい。慣例的に,それらは言葉の適切な一部としてよい。 定数名の例には,クラスCharacter
のMIN_VALUE
, MAX_VALUE
,
MIN_RADIX
及びMAX_RADIX
を含む。集合の選択肢の値,又は,それほど多くはないが,整数値におけるビットマスクを表す定数群は,時々便利なのだが ,次のとおり前置名として共通の頭文字で指示することがある。
定数名を含む不明瞭化は少ない。interface ProcessStates { int PS_RUNNING = 0; int PS_SUSPENDED = 1; }
ColoredPoint
への参照を保持する変数のための cp
などとする。
buffer
へのポインタを保持するbuf
などとする。
一時変数及びループ変数,又は変数が型の特別でない値を保持する場合を除いて,1文字の局所変数名又は仮引数名は避けることが望ましい。 慣例的な1文字の名前は次のとおり
byte
に対するb
。
char
に対するc
。
double
に対するd
。
Exception
に対するe
。
float
に対するf
。
i
, j
,k
。
long
に対するl
。
Object
に対するo
。
String
に対するs
。
v
。
目次 | 前 | 次 | 索引 | Java言語規定 第2版 |