目次 | |

6. 名前

名前は,Javaプログラムで宣言した実体を参照するために使用する。宣言した実体(6.1)は,パッケージ,クラス型,インタフェース型,参照型のメンバ(フィールド又は,メソッド),(メソッド,コンストラクタ又は例外ハンドラに対する)仮引数又は局所変数とする。

Javaプログラムにおける名前は,単一の識別子で構成される単純名又は"."トークンで区切られる識別子の並びから構成される限定名 (6.2)のいずれかとする。

宣言によって導入したすべての名前は, 有効範囲(scope) (6.3)をもつ。有効範囲とは,その中から,宣言した実体が単純名によって参照できるJavaプログラムテキストの一部分とする。

パッケージ及び参照型(つまり,クラス型,インタフェース型及び配列型)は,メンバ(6.4)をもつ。メンバは,限定名 N.x を使用して参照可能とする。 ここで N は単純名又は限定名とし, x は識別子とする。N がパッケージに名前付けをしていれば,x はそのパッケージのメンバ,つまり,クラス型,インタフェース型又はサブパッケージのいずれかとする。 N が参照型又は参照型の変数に名前付けしていれば,x はその型のメンバ,フィールド又はメソッドに名前を付ける。

名前の意味の決定(6.5)において,Javaは同じ名前をもったパッケージ,型,変数及びメソッドの間のあいまいさを解消するために,名前が出現する文脈を使用する。

アクセス制御(6.6)は,メンバへのアクセス(access)が許可されるときを制御するために,クラス,インタフェース,メソッド又はフィールドの宣言で指定できる。アクセスは,有効範囲とは異なる概念とする。アクセスは,宣言した実体が,限定名,フィールドアクセス式(15.10)又はメソッドを単純名で指定しない場合のメソッド呼出し式(15.11) によって参照できる,Javaプログラムテキストの部分を指定する。 デフォルトアクセスは,メンバ宣言を含んでいるパッケージ内のどこからでも,そのメンバにアクセス可能とする。その他の可能性は,publicprotected 及び private とする。

完全限定名(6.7)及び名前付け規約(6.8)についてもこの章で述べる。

フィールド,仮引数又は局所変数の名前は,式(15.13.1)として使用できる。 メソッドの名前は,メソッド呼出し式(15.11)の一部としてだけ式に出現してよい。 クラス又はインタフェース型の名前は,クラスインスタンス生成式(15.8),配列生成式(15.9),キャスト式(15.15),若しくは instanceof(15.19.2)の一部分,又はフィールド若しくはメソッドに対する限定名の一部としてだけ式に出現してよい。 パッケージの名前は,クラス型又はインタフェース型の限定名の一部としてだけ式に出現してよい。

6.1 宣言

宣言(declaration) は,Javaプログラムに実体を導入し,この実体を参照するために名前として使用できる識別子(3.8)を取り入れる。宣言される実体は,次のいずれかとする。

コンストラクタ(8.6)もまた宣言によって導入される。しかし新しい名前を導入せずに,宣言されているクラスの名前を使用する。

6.2 名前及び識別子

名前(name) は,Javaプログラムで宣言した実体を参照するために使用する。

名前には二つの形式が存在する。単純名及び限定名とする。単純名(simple name) は,単一の識別子とする。限定名(qualified name) は,名前,"." トークン及び識別子から構成する。

名前の意味の決定 (6.5)において,Java言語は,名前が出現する文脈を考慮する。Java言語は,文脈の中のどこで,名前が,パッケージ(6.5.3),型(6.5.4),式における変数若しくは値 (6.5.5),又はメソッド(6.5.6)を表示(参照)しなければならないかを識別する。

Javaプログラムにおけるすべての識別子が,名前の一部とは限らない。識別子は,次の状況においても使用する。

次に例を示す。


class Test {
	public static void main(String[] args) {
		Class c = System.out.getClass();
		System.out.println(c.toString().length() +
					args[0].length() + args.length);
	}
}
識別子 Testmain 並びに最初に出現する args 及び c は名前としない。むしろこれらは,宣言した実体の名前を指定するために使用する。名前 StringClassSystem.out.getClass, System.out.printlnc.toStringargs 及び args.length が例で出現している。length の最初の出現は名前とはしない。メソッド呼出し式(15.11)で出現する識別子とする。二番目に出現する length も名前とはしない。 メソッド呼出し式(15.11)で出現する識別子とする。

ラベル付き文,並びにそれに関連のある 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(20.12.26)のある版からもって来た。元の版では,ラベルは test と呼ばれていた。 ラベルを,局所変数 i と同じ名前をもつように変更しても,i の宣言の有効範囲においてそのラベルを隠ぺいすることはない。 識別子 max も,文ラベルとして使用できた。つまり,ラベルは,ラベル付き文内の局所変数 max を隠ぺいしない。

6.3 単純名の有効範囲

宣言の有効範囲(scope)は,宣言によって宣言した実体が,単純名を使って参照可能なプログラムの領域とする。


	class Test {
		int i = j;	// compile-time error: incorrect forward reference
		int j = 1;
	}

	class Test {
		Test() { k = 2; }
		int j = 1;
		int i = j;
		int k;
	}
これらの規則は,クラス及びインタフェース型の宣言が,型の使用前に出現する必要が無いことを示唆している。

次に例を示す。

package points;

class Point {
	int x, y;
	PointList list;
	Point next;
}

class PointList {
	Point first;
}
クラス PointPointList の使用は正しい。 これはクラス型の名前 PointList の有効範囲が,パッケージ points の他のコンパイル単位における他の型宣言でも同様に,クラス Point 及びクラス PointList の両方を含むからとする。

6.3.1 隠ぺいされる名前

宣言は,同じ名前の他の宣言によって,有効範囲の一部を隠ぺい(6.3.1)されることがある。この場合,単純名は宣言した実体を参照するために使用できない。

次に例を示す。


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
この例は,次のものを宣言している。

クラス変数の有効範囲は,クラス(8.2)の本体の全体を含むので,クラス変数 x はメソッド main の本体の全体を通して普通に利用できる。 しかしこの例では,局所変数 x の宣言によって,クラス変数 x はメソッド main の本体内で隠ぺいされる。

局所変数は,宣言(14.3.2)されたブロックの残りの部分を有効範囲とする。 この例の場合,これはメソッド main の本体の残りの部分,つまり,初期化子"0" 並びに print 及び println の呼出しの部分とする。

これは次を意味する。

標準の名前付け規約(6.8)に従っていれば,別々の名前付け文脈の識別が問題となる隠ぺいはほとんど存在しない。次の意図的な例は,標準の名前付け規約に従っていないために隠ぺいを含んでいる。


class Point { int x, y; }

class Test {

	static Point Point(int x, int y) {
		Point p = new Point();
		p.x = x; p.y = y;
		return p;
	}

public static void main(String[] args) { int Point; Point[] pa = new Point[2]; for (Point = 0; Point < 2; Point++) { pa[Point] = new Point(); pa[Point].x = Point; pa[Point].y = Point; } System.out.println(pa[0].x + "," + pa[0].y); System.out.println(pa[1].x + "," + pa[1].y); Point p = Point(3, 4); System.out.println(p.x + "," + p.y); }
}
これはエラー無しにコンパイルされ,実行すると次を出力する。


0,0
1,1
3,4
main の本体内では,Point の参照ごとに,それを使用する文脈に依存した別々の宣言を見つけることとなる。

次に例を示す。

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.4 メンバ及び継承

パッケージ及び参照型は, メンバ(members) をもつ。 パッケージ(7)のメンバは,サブパッケージ(7.1)並びにそのパッケージのすべてのコンパイル単位(7.3)において宣言された,すべてのクラス(8)型及びインタフェース(9)型とする。 参照型(4.3)のメンバは,フィールド(8.39.310.7)及びメソッド(8.49.4)とする。メンバは,型の中で宣言されるか,若しくは隠ぺいも上書き(8.4.6)もされないアクセス可能なスーパクラス又はスーパインタフェースのメンバであることにより 継承 (inherited) されているものとする。

6.4では,限定名の議論及び名前の意味の決定についての背景として,パッケージ及び参照型のメンバの概要を示す。メンバの完全な説明については,7.18.29.2 及び 10.7を参照のこと。

6.4.1 パッケージのメンバ

パッケージ(7)のメンバは,サブパッケージ(7.1)又はそのパッケージのコンパイル単位(7.3)で宣言されたクラス型(8)若しくはインタフェース(9)型とする。

一般に,あるパッケージのサブパッケージは,ホストシステム(7.2)によって決定される。しかし,標準パッケージ java は,常に サブパッケージlangutilio及びnet を含み,さらに,その他のサブパッケージを含んでもよい。同じパッケージの二つの異なるメンバは,同じ単純名(7.1)をもってはならない。しかし異なるパッケージのメンバは,同じ単純名をもってもよい。例えば,次のパッケージ宣言は可能とする。

package vector;
public class Vector { Object[] vec; }
これは標準パッケージ java.util が, Vector という名前のクラスを宣言しているのにもかかわらず,Vector という名前のpublic クラスをメンバとしてもつ。これら二つのクラス型は,これらが異なる完全限定名(6.7)をもつ事実によって分かるように,異なっている。この例の Vector の完全限定名は vector.Vector とする。これに対して java.util.Vector が,標準クラス Vector の完全な限定名である。パッケージ vectorVector という名前のクラスを含むので, Vector という名前のサブパッケージをもつことはできない。

6.4.2 クラス型のメンバ

クラス型(8.2)のメンバは,フィールド及びメソッドとする。クラス型のメンバは,次に示すものすべてとする。

コンストラクタ(8.6)はメンバとしない。

同じ単純名をもつクラス型のフィールド及びメソッドに対する制限は存在しない。

異なるインタフェースで宣言され継承されるならば,クラスは同じ名前で二つ以上のフィールドをもってよい。ただし,そのフィールドを単純名で参照しようとすると,コンパイル時エラーを生じる(6.5.6.28.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.11で与えられたオーバロード解決手順によってコンパイル時に決定される。

この例では,クラス Point のメンバは,Point で宣言された float インスタンス変数 x 及び y,二つの宣言されたメソッド move,宣言されたメソッド toString,並びにメソッド hashCode (20.1.4)のような Point がその暗黙の直接的ス−パクラス Object から継承するメンバ,とする。Point はクラス Object のメソッド toString(20.1.2)を継承していないことに注意すること。これは,そのメソッドがクラス Point 内のメソッド toString の宣言によって上書きされているからである。

6.4.3 インタフェース型のメンバ

インタフェース型(9.2)のメンバは,フィールド及びメソッドとする。インタフェースのメンバは,次のすべてとする。

インタフェースは,異なるインタフェースで宣言及び継承されるならば,同じ単純名をもつ二つ以上のフィールドをもってよい。ただし,そのようなフィールドを単純名で参照しようとするとコンパイル時エラーが発生する(6.5.5.19.2)。

次に例を示す。


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 から継承したメンバ,つまり,WHITEBLACK(二つの内の最初),CYANMAGENTAYELLOW,及び BLACK(二つの内の二番目)を含む。メンバ名 BLACK はインタフェース ColorsAndSeparates ではあいまいとする。

6.4.4 配列型のメンバ

配列型(10.7)のメンバは,次のすべてとする。

次に例を示す。


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[]のインスタンスであることを示す。

6.5 名前の意味の決定

Javaにおける名前の意味は,それが使われる文脈に依存する。名前の意味の決定は,三段階を必要とする。第一に,文脈は構文的に名前を五つの分類,つまり,パッケージ名(PackageName)型名(TypeName)式名(ExpressionName)メソッド名(MethodName)又はあいまい名(AmbiguousName) のうちの一つに分類する。第二に,最初に文脈によって あいまい名(AmbiguousName) に分類された名前は,特定の有効範囲の規則によって,パッケージ名(PackageName)型名(TypeName)又は式名(ExpressionName) に再分類される。第三に,分類結果が名前の意味を最終的に決定する。(名前が意味をもたなければ,コンパイル時エラーとする。)

Javaにおける文脈の使用は,異なる種類の実体間の名前の衝突を最小にすることを助ける。6.8で説明される名前付け規約に従っていれば,このような衝突が発生することはほとんどない。それにもかかわらず,名前の衝突は,違うプログラマ又は違う組織での開発の進展の典型として,故意ではなく発生することがある。たとえば,型,メソッド及びフィールドが同じ名前をもつことがある。Javaでは,名前を使用する文脈が,必ず,名前がメソッドか又はフィールドであるかを明らかにするため,同じ名前をもつメソッドとフィールドの間の識別には問題が生じない。

6.5.1 文脈に従った名前の構文上の分類

次の文脈では,名前を構文上, パッケージ名(PackageName) として分類する。

次の文脈では,名前を構文上, 型名(TypeName) として分類する。

次の文脈では,名前を構文上, 式名(ExpressionName) として分類する。

次の文脈では,名前を構文上,メソッド名(MethodName) として分類する。

次の文脈では,名前を構文上, あいまい名(AmbiguousName) として分類する。

6.5.2 文脈的にあいまいな名前の再分類

あいまい名(AmbiguousName) は次のとおり再分類する。

例として,次のとおり設計された"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) として分類する。その理由は,それはPostfix式(PostfixExpression) として機能するからである。従って,次の各名前,


ORG.rpgpoet.Music.wizards
ORG.rpgpoet.Music
ORG.rpgpoet
ORG
は,最初は あいまい名(AmbiguousName) として分類する。これらはその後再分類する。

6.5.3 パッケージ名の意味

パッケージ名(PackageName) として分類した名前の意味は,以下のように決める。

6.5.3.1 単純パッケージ名

パッケージ名が単一の 識別子(Identifier) で構成されていれば,この識別子は,その識別子によって名前付けられた最上位のパッケージ名を表示する。ホストシステム(7.4.3)によって決められた方法でアクセス可能なその名前をもつパッケージが存在しなければ,コンパイル時エラーが発生する。

6.5.3.2 限定パッケージ名

パッケージ名が形式 Q.Id ならば,Q もパッケージ名でなければならない。パッケージ名 Q.Id は, Q という名前のパッケージ内の,Id という名前のメンバのパッケージに名前付けする。Q がアクセス可能なパッケージに名前付けするか,又は Id がそのパッケージのアクセス可能なサブパッケージに名前付けしなければ,コンパイル時エラーが発生する。

6.5.4 型名の意味

型名(TypeName) として分類した名前の意味は,以下のように決定する。

6.5.4.1 単純型名

型名が単一の 識別子(Identifier) で構成されていれば,その識別子は,この名前をもつ型の宣言の有効範囲内に出現しなければならない。そうでないときには,コンパイル時エラーが発生する。識別子は,その名前をもつ一つより多くの型の有効範囲内に出現することが可能とする。この場合,その名前が表す型は,次のとおり決定する。

型宣言を考察するこの順番は,二つ以上の適用可能な型宣言の内の最も明示的なものを選択するために設計されている。

6.5.4.2 限定型名

型名が形式 Q.Id ならば, Q はパッケージ名でなければならない。型名 Q.Id は,名前がQ のパッケージ内の,名前がId というメンバの型に名前を与える。Q がアクセス可能なパッケージ名でないか,Id がそのパッケージ内の型名でないか,又はそのパッケージ内の Id という名前の型がアクセス可能(6.6)でなければ,コンパイル時エラーが発生する。

次に例を示す。

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
この例では,

6.5.5 式名の意味

式名(ExpressionName) として分類した名前の意味は,以下のように決定する。

6.5.5.1 単純式名

式名が単一の 識別子(Identifier) から構成されている場合。

次に例を示す。


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); }
}
iv及びf への代入の左辺で使用している名前は,局所変数 i,フィールド v及びf の値(変数 f ではない。その理由は,ffinal 変数だからとする。)を表す。したがって,最後の代入の左辺が変数ではないために,この例はコンパイル時エラーを生じる。エラーとなる代入を削除すれば,修正したコードはコンパイルでき,次の結果を出力する。

1 2 3

6.5.5.2 限定式名

式名が形式 Q.Idならば,Q は既に,パッケージ名,型名又は式名として分類されている。

次に例を示す。


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 のメソッドでないことのためである。

6.5.6 メソッド名の意味

メソッド名(MethodName) は,メソッド呼出し式(15.11)にだけ出現できる。メソッド名(MethodName) として分類した名前の意味は,以下のように決定する。

6.5.6.1 単純メソッド名

メソッド名が単一の 識別子(Identifier) から構成されていれば,その識別子(Identifier) はメソッド呼出しで使用するメソッド名とする。その識別子(Identifier) は,その識別子(Identifier)が出現する宣言内のクラス又はインタフェースのメソッドを少なくとも一つは名前付けしなければならない。メソッド呼出し式における単純メソッド名の解釈についての詳細な解説は15.11を参照のこと。

6.5.6.2 限定メソッド名

メソッド名が形式 Q.Id ならば,Q は,パッケージ名,型名又は式名として既に分類されている。Q がパッケージ名ならば,コンパイル時エラーが発生する。そうでないときには,Id はメソッド呼出しのために使用するメソッド名とする。Q が型名ならば,Id は型 Qstatic メソッドを少なくとも一つ名前付けしなければならない。Q が式名ならば,T を式 Q の型とする。Id は型 T のメソッドを少なくとも一つ名前付けしなければならない。メソッド呼出し式における限定メソッド名の解釈の詳細な解説は15.11を参照のこと。

6.6 限定名及びアクセス制御

限定名は,パッケージ又は参照型のメンバへのアクセスの方法とする。関係するアクセスの方法は,フィールドアクセス式(15.10)及びメソッド呼出し式(15.11)を含む。三つのすべては,パッケージ,型又は型をもつ式の指示が先行し,パッケージ又は型のメンバを名前付けする識別子(Identifier) が続く,"." が出現する,という点で構文的に類似する。これらは,まとめて限定アクセス(qualified access) のための構文要素として知られる。

Javaは,パッケージ又はクラスのユーザが,そのパッケージ又はクラスの実装の不必要な詳細に依存することを防止するために,アクセス制御(access control) の機構を提供する。アクセス制御は,限定アクセス並びにクラスインスタンス生成式(15.8),明示的なコンストラクタ呼出し (8.6.5)及びクラス Class のメソッド newInstance(20.3.6)によるコンストラクタの呼出しに適用する。

アクセスが許可されるならば,アクセスされる実体はアクセス可能(accessible) という。

6.6.1 アクセス性の決定

6.6.2 protected アクセスの詳細

あるオブジェクトの protected メンバ又はコンストラクタは,そのオブジェクトの実装に対して責任があるコードによってだけ,それを宣言したパッケージの外部からアクセスしてよい。Cprotected メンバ又はコンストラクタを宣言しているクラスとし,Sprotected メンバ又はコンストラクタの使用が発生する C のサブクラスとする。

6.6.3 アクセス制御の例

アクセス制御の例のために,二つのコンパイル単位を考える。


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; }
}
パッケージ Point 内では,二つのクラス型を宣言する。

protected アクセス修飾子がアクセスを制限する方法の例については6.6.7を参照のこと。

6.6.4 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 を,以下のどちらの方法によってでもアクセスできる。

まず,完全限定名を使用する例を次に示す。


package pointsUser;

class Test {
	public static void main(String[] args) {
		points.Point p = new points.Point();
		System.out.println(p.x + " " + p.y);
	}
}
さらに,完全限定名を記述する単一の型インポート宣言(7.5.1)を使用し,その結果,それ以降単純名が使用できる例を次に示す。


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 の外からはアクセス可能ではないからである。

6.6.5 フィールド,メソッド及びコンストラクタのデフォルトアクセスの例

アクセス修飾子publicprotected,又はprivate をいずれも指定していなければ,クラスメンバ又はコンストラクタは,そのクラスメンバを宣言しているクラスの宣言を含むパッケージの全体からアクセス可能とする。しかし,そのクラスメンバ又はコンストラクタは,他のパッケージからはアクセス不可能とする。public クラスが,デフォルトアクセスのメソッド又はコンストラクタをもてば,このメソッド又はコンストラクタは,このパッケージの外で宣言したサブクラスによってアクセス又は継承されることはないとする。

次に例を示す。


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); }
}
他のパッケージ内のサブクラスは同じシグネチャ (8.4.2)及び返却値の型をもつ関連のないメソッド 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);
	}
}
PointmovePlusPoint 内のmove によって上書きされないため,Point 内のメソッド moveAlsoPlusPoint 内のメソッド 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);
    }

}
PointmovePlusPoint 内の move によって上書きされれば,このプログラムは,StackoverflowError が発生するまで無限に再帰するであろう。

6.6.6 public フィールド,メソッド及びコンストラクタの例

public クラスのメンバ又はコンストラクタは,それを宣言しているパッケージの全体から,及びそれを宣言しているパッケージにアクセスするすべての他のパッケージから,アクセス可能とする(7.4.4)。例えば,次のコンパイル単位を考える。


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 及びフィールド movespublic メンバとしてもつ。これらの public メンバは,パッケージ points にアクセスする他の任意のパッケージに対してアクセス可能とする。フィールド x 及び ypublic ではなく,パッケージ points 内からでだけアクセス可能とする。

6.6.7 protected フィールド,メソッド及びコンストラクタの例

パッケージ point を宣言する次の例を考える。


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 で,コンパイル時エラーが発生する。つまり,仮引数 pprotected メンバ x 及び y にはアクセスできない。その理由は, Point3d(フィールド x 及びy への参照が発生するクラス)は,Pointx 及びy を宣言するクラス)のサブクラスだが,これは,Point(仮引数 p の型)の実装には含まれないためである。メソッド delta3d は,仮引数 qprotected メンバにアクセス可能とする。その理由は,クラス Point3d は,Point のサブクラスであって,Point3d の実装に含まれるからである。

メソッド delta は,その仮引数を Point3d とするキャスト(5.415.15)を試みることはできるが,実行時の p のクラスが Point3d でなければ,このキャストは失敗し,例外を発生する。

メソッド warp でもコンパイル時エラーが発生する。仮引数 aprotected メンバ z にアクセスできない。その理由は,クラス Point(フィールド z への参照が発生するクラス)は,Point(仮引数 a の型)の実装に関連しているが,Point z を宣言したクラス)のサブクラスでないからである。

6.6.8 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.6.8を参照のこと。

6.7 完全限定名

すべてのパッケージ,クラス,インタフェース,配列型及びプリミティブ型は,完全限定名をもつ。したがって,空型を除くすべての型は完全限定名をもつ。

次に例を示す。

次に例を示す。

package points;

class Point { int x, y; }

class PointVec {
	Point[] vec;
}
Point の完全限定名は"points.Point",型 PointVec の完全限定名は"points.PointVec"及びクラス PointVecvec フィールドの型の完全限定名は"points.Point[]"とする。

6.8 名前付け規約

Javaシステム及び標準クラスでは,可能な限りここで説明する規約にそって選択された名前を使用する。これらの規約は,コードをより読み易くし,ある種の名前の競合を回避すること支援する。

すべてのJavaプログラムで,以下の規約を使用することが望ましい。しかし,長期間にわたり使用してきた,慣用的な使用法が本規約と異なるならば,本規約に,無条件に従う必要は無い。例えば,クラス java.lang.Math のメソッド sin 及びメソッド cos は,短く,動詞ではないという理由でJavaの規約を守っていないが,数学的な慣用名をもつ。

6.8.1 パッケージ名

パッケージの名前を広く利用可能にするには,7.7で述べる形式に従うことが望ましい。そのような名前は,常に,COMEDUGOVMILNET若しくは ORG のようなインターネットドメイン又は UK 若しくは JP のような2文字のISO国コードを示す,最初の識別子を2文字又は3文字の大文字で構成する限定名とする。この規約に従って作成した架空の一意な名前の例を次に示す。


COM.JavaSoft.jag.Oak
ORG.NPR.pledge.driver
UK.ac.city.rugby.game
局所使用だけを意図したパッケージの名前は,小文字で始まる識別子をもつことが望ましい。しかし,その最初の識別子を java とするのは望ましくない。識別子 java で始まるパッケージ名は,標準Javaパッケージを名前付けするためにJavaSoftが予約している。

式にパッケージ名が出現するときは,次のとおりとする。

6.8.2 クラス及びインタフェース型名

クラス型の名前は,各単語の先頭文字を大文字とし,大文字及び小文字を混在させた,過度に長くない,記述的な名詞又は名詞句であることが望ましい。

次に例を示す。


ClassLoader
SecurityManager
Thread
Dictionary
BufferedInputStream
同様に,インタフェース型の名前は,各単語の先頭文字を大文字とし,大文字及び小文字を混在させ,短く,記述的で過度に長くないことが望ましい。その名前は,記述的な名詞又は名詞句であってよい。これは,インタフェース java.io.DataInput 及び java.io.DataOutput のように,インタフェースを,抽象スーパクラスであるかのように使用するときに適している。名前は,インタフェースjava.lang.Runnable 及び java.lang.Cloneable のように,振舞いを記述する形容詞としてもよい。

クラス及びインタフェース型の名前を隠ぺいすることはほとんどない。規約により,フィールド,仮引数及び局所変数の名前は小文字で始まるのに対して,型名は大文字で始まるので,普通は,型名を隠ぺいしない。 

6.8.3 メソッド名

メソッド名は,先頭文字を小文字とし,それに続く各単語の先頭文字を大文字とする,大文字及び小文字を混在させた動詞又は動詞句とすることが望ましい。メソッド名に対する付加的で特別な規約を次に示す。

可能及び適切なときはいつでも,新しいクラスのメソッドの名前は,類似した既存のクラス,特に標準Javaアプリケーションプログラミングインタフェースクラス,の名前をもとにすると使いやすくなる。

メソッド名は,他の名前を隠ぺいしたり,他の名前で隠ぺいされたりできない(6.5.6)

6.8.4 フィールド名

final でないフィールドの名前は,先頭文字は小文字で始まり,それに続く単語の先頭文字を大文字とした,大文字及び小文字を混在したものとすることが望ましい。適切に設計されたJavaクラスは,定数のフィールド(final static フィールド) (6.8.5)を除くと,public 又は protected フィールドは非常に少ないことに注意すること。

フィールドは,名詞,名詞句又は名詞の省略形の名前をもつことが望ましい。この規約の例としては,クラス java.io.ByteArrayInputStream (22.6)のフィールド bufpos 及び count 並びにクラス java.io.InterruptedIOException (22.30.1)のフィールド bytesTransferred がある。

フィールド名を含む隠ぺいはほとんどない。

6.8.5 定数名

インタフェース型における定数の名前は,下線"_"で区切られた構成要素をもつ,すべて大文字の,一つ以上の単語,頭文字又は略語の並びとすることが望ましい。クラス型の final 変数も,慣例として,同じ並びとしてよい。定数名は,記述的であって,不必要に省略しないことが望ましい。慣例的に,それらは言葉の適切な一部としてよい。定数名の例には,クラス java.lang.CharacterMIN_VALUEMAX_VALUEMIN_RADIX 及び MAX_RADIX を含む。

集合の選択肢の値,又は,それほど多くはないが,整数値におけるビットマスクを表す定数群は,時々便利なのだが,次のとおり前置名として共通の頭文字で指示することがある。


interface ProcessStates {
	int PS_RUNNING = 0;
	int PS_SUSPENDED = 1;
}
定数名を含む隠ぺいは少ない。

6.8.6 局所変数及び仮引数名

局所変数及び仮引数名は,短いが意味のあるものとすることが望ましい。これらは,普通,単語ではない短い小文字の列とする。

次に例を示す。

一時変数及びループ変数,又は変数が型の特別でない値を保持する場合を除いて,1文字の局所変数名又は仮引数名は避けることが望ましい。

慣例的な1文字の名前は次のとおり。

2個又は3個の大文字だけから構成される局所変数又は仮引数名は,一意なパッケージ名(7.7)の先頭の構成要素とする,国コード及びドメイン名との衝突の可能性を避けるために,使用しないことが望ましい。


目次 | |