目次 | |

4. 型,値及び変数

Javaを,強く型付けされた(strongly typed) 言語にした。それは,個々の変数及び個々の式がコンパイル時に既知の型をもつことを意味する。型は,変数(4.5)が保持できるか,又は式が生成できる値を制限し,それらの値に対する演算を制限し,演算の意味を決定する。強い型付けは,コンパイル時にエラーを検出するのに役立つ。

Java言語の型は,二つのカテゴリ,プリミティブ型及び参照型に分けられる。プリミティブ型(4.2)は, boolean型(論理型)及び数値型に分ける。数値型は,整数的な型である byteshortintlong 及び char,並びに浮動小数点型である float 及び double に分ける。参照型(4.3)は,クラス型,インタフェース型,及び配列型に分ける。特別な型 null もある。Javaのオブジェクト(4.3.1)は,動的に生成されたクラス型のインスタンス又は動的に生成された配列になる。参照型の値は,オブジェクトへの参照になる。配列を含むすべてのオブジェクトは,クラス Object(4.3.2)のメソッドを処理できる。文字列リテラルは,オブジェクト String(4.3.3)によって表す。

いくつかの型が同じ完全限定名をもち,同じクラスローダによってロードされていれば,それらは同じ型になる(4.3.4)。型の名前は,宣言,キャスト,クラスインスタンス生成式,配列生成式,及び instanceof 演算式において使用する(4.4)

変数(4.5)は,記憶域の位置に他ならない。プリミティブ型の変数は,常に厳密なその型の値を保持する。クラス型 T の変数は,空参照又はクラス T 若しくは T のサブクラスである任意のクラスのインスタンスへの参照を保持する。インタフェース型の変数は,空参照又はそのインタフェースを実装する任意のクラスの任意のインスタンスへの参照を保持する。 T がプリミティブ型ならば,“T の配列”型の変数は,空参照又は“Tの配列”型の任意の配列への参照を保持する。T が参照型ならば,“T の配列”型変数は,空参照又は型 T に代入可能な(5.2)S の“S の配列”型の任意の配列への参照を保持する。型 Object の変数は,空参照又はクラスインスタンス若しくは配列の任意のオブジェクトへの参照を,保持する。

4.1 型及び値の種類

Javaには2種類の 型(types),プリミティブ型(4.2)及び参照型(4.3)が存在する。それぞれに対応して,変数に記憶できる,実引数として渡され,メソッドによって返され,演算対象となる,プリミティブ値(4.2)及び参照値(4.3)という2種類のデータ値が存在する。

null の型である特別な 空型(null type) も存在する。それには名前がない。空型には名前がないので,空型の変数を宣言すること又は空型にキャストすることはできない。空型の式が取りうる唯一の値が空参照となる。 空参照は,常に任意の参照型にキャストできる。実際には,Javaプログラマは,空型を無視し,空型は任意の参照型となれる単なる特別なリテラルであると見なしても良い。

4.2 プリミティブ型及び値

プリミティブ型(primitive type) は,Java言語によってあらかじめ決められており,それに対して予約されたキーワード(3.9)で名前付けする。

プリミティブ値は,他のプリミティブ値と状態を共有しない。型をプリミティブ型とする変数は,常にそれと同じ型のプリミティブ値を保持する。プリミティブ型の変数の値は,その変数に対する代入演算によってだけ変更できる。

数値型(numeric types) は,整数的な型及び浮動小数点型とする。

整数的な型(integral types) は,byteshortint 及び long(それぞれ,8ビット,16ビット,32ビット及び64ビットの2の補数符号付き整数),並びに char(Unicode文字を表す16ビット符号無し整数)に分ける。

浮動小数点型(floating-point types) は,float(32ビットIEEE 754浮動小数点数)及び double(64ビットIEEE 754浮動小数点数)とする。

boolean は二つの値,true(真)及びfalse(偽),だけをとる。

4.2.1 整数的な型及び値

整数的な型の値は,次の範囲の整数とする。

4.2.2 整数演算

Javaは,整数的な値に作用する多くの演算子を提供する。

他の有益なコンストラクタ,メソッド及び定数が,クラス Integer(20.7),クラス Long(20.8)及びクラス Character(20.5)で定義してある。

シフト演算子以外の整数演算子が少なくとも一つの型 long のオペランドをもてば,演算を64ビット精度で実行し,その結果を型 long とする。片方のオペランドが long でなければ,最初に数値昇格(5.6)によって型 long に拡張する(5.1.2)。そうでなければ,演算は32ビット精度で実行し,その数値演算子の結果は型 int とする。どちらかのオペランドが int でなければ,演算に先立って数値昇格によって型 int に拡張する。

組み込みの整数演算子は,どのような形でもオーバフロー又はアンダフローを示さない。例外(11.)を投げることのできる数値演算子は,整数除算演算子 / (15.16.2)及び整数剰余演算子 % (15.16.3)だけとする。これは,右辺オペランドがゼロならば,ArithmeticException を投げる。

次に例を示す。


class Test {
	public static void main(String[] args) {
		int i = 1000000;
		System.out.println(i * i);
		long l = i;
		System.out.println(l * l);
		System.out.println(20296 / (l - i));
	}
この例は,次の出力を生成する。


-727379968
1000000000000 
l - i はゼロなので,l - i による除算で ArithmeticException を生じる。最初の乗算は32ビット精度で実行するが,2番目の乗算は, long 乗算となる。値 -727379968 は,型 int では大き過ぎる値の数学的な結果 1000000000000 の下位32ビットの10進数値である。

任意の整数的な型の任意の値は,任意の数値型へ又は任意の数値型からキャストしてもよい。整数的な型及び型 boolean の間では,キャストはできない。

4.2.3 浮動小数点型及び値

浮動小数点型は,float 及び double とし,2進数浮動小数点計算のためのIEEE規格(IEEE Standard for Binary Floating-Point Arithmetic),ANSI/IEEE規格754-1985(IEEE, New York)で規定する,単精度32ビット及び倍精度64ビット形式のIEEE 754の値及び演算を表現する。

IEEE 754規格は,正負の符号及び大きさからなる数だけではなく,正及び負のゼロ,正及び負の 無限大(infinities),並びに特別な Not-a-Number (以降NaNと略す)を含む。NaN値は,ゼロをゼロで割るなどの特別な演算の結果を表すために使用する。float 及びdouble型のNaN定数は,Float.NaN (20.9.5)及び Double.NaN (20.10.5)として,定義する。

float の有限非ゼロ値の形式は,s*m*2**eとする。ここで s は, +1又は -1,m は,2**24未満の正整数とし,e は, -149 以上 104 以下の整数とする。m が正であるが2**23未満であって,e が -149 に等しい形式の値を,非正規化(denormalized) されているという。

double の有限非ゼロ値の形式は,s*m*2**eとする,ここで s は, +1 又は -1,m は,2**53未満の正整数であり,e は, -1075 以上 970 以下の整数とする。m が正であって2**52未満及び e が -1075 に等しい形式の値を,非正規化(denormalized)されているという。

NaNを除いて,浮動小数点値は最小値から最大値に向かって,負の無限大,負の有限非ゼロ値,負のゼロ,正のゼロ,正の有限非ゼロ値,及び正の無限大の順に 順序付ける(ordered)

正のゼロと負のゼロの比較結果は,等しいとする。したがって,式 0.0==-0.0 の結果は true に,0.0>-0.0 の結果は false になる。しかし,その他の演算は,正及び負のゼロを区別する。例えば,1.0/0.0 は正の無限大の値をもつ。一方,1.0/-0.0 の値は負の無限大とする。Math.min 及び Math.max 演算も,正のゼロ及び負のゼロを区別する。

NaNは,順序付けしない(unordered)。したがって,数値比較演算子 <<=> 及び >= は,オペランドのいずれか又は両方がNaN (15.19.1)のとき false を返す。どちらかのオペランドがNaNならば,等価演算子 ==false を返し,どちらかのオペランドがNaN(15.20.1)ならば,非等価演算子 !=true を返す。特に, x がNaNのときに限って,x!=xtrue を, x 又は y がNaNならば,(x<y) ==!(x>=y)false を返す。

浮動小数点型の任意の値は,任意の数値型へキャストしてよい。又は任意の数値型からキャストされてもよい。浮動小数点型と型 boolean との間では,キャストできない。

4.2.4 浮動小数点演算

Javaは,浮動小数点値に作用する演算子を多数提供する。

他にも有用なコンストラクタ,メソッド及び定数を,クラス Float(20.9),クラス Double(20.10) 及びクラス Math(20.11)の中で定義する。

二項演算子に対するオペランドのうち少なくとも一つが,浮動小数点型ならば,他方が整数的であっても,演算は,浮動小数点演算とする。

数値演算子のオペランドのうち少なくとも一つが,型 double ならば,演算を64ビット精度浮動小数点計算によって実行し,その数値演算子の結果を,型 double の値にする。(他方のオペランドが double でなければ,演算に先立って,数値昇格(5.6)によって型 double に拡張する。)そうでなければ,演算は32ビット精度浮動小数点計算によって実行し,その数値演算子の結果は,型 float の値とする。他方のオペランドが float でなければ,演算に先立って,数値昇格によって型 float に拡張する。

浮動小数点数に対する演算は,正確にIEEE 754で規定したとおりに振る舞うものとする。特に,Javaは,IEEE 754の 非正規化(denormalized) 浮動小数点数及び緩やかなアンダフロー(gradual underflow) を扱う必要がある。これらは,数値アルゴリズムの望ましい特性の証明を容易にする。Javaにおける浮動小数点演算は,計算結果が非正規化数ならば,“ゼロにフラッシュする”ことはない。

Javaは,すべての浮動小数点演算子が,その浮動小数点の結果を,結果精度に丸めたかのように振る舞う計算を必要とする。不正確(Inexact) な結果は,正確な結果に限りなく最も近い表現可能値に丸めなければならない。二つの同程度に近い代表値があるときは,もっとも重みのないビット(Least Significant Bit,LSB)がゼロのものが選ばれる。これが,直近への丸め(round to nearest) として知られている,IEEE 754規格のデフォルト丸めモードである。

Javaは,浮動小数点値を整数(5.1.3)に変換するときに,ゼロに向かう丸め(round toward zero) を適用する。この場合には,仮数ビットを切り捨てるように動作する。ゼロに向かう丸めでは,その形式の値が,大きさに関して正確な値に限りなく最も近くて,しかも大きくない結果を選ぶ。

Javaの浮動小数点演算子は,例外(11.)を引き起こさない。オーバフローを生じる演算は,符号付き無限大を返し,アンダフローを引き起こす演算は,符号付きゼロを返し,数学的に確定した結果をもたない演算は,NaNを返す。オペランドとしてNaNをもつすべての数値演算は,結果としてNaNを返す。既に規定したとおり,NaNは順序付けしない。したがって,一つ又は二つのNaNを含む数値比較演算は false を返し,NaNを含む != 比較は true を返す。これは,x がNaNであるときのx!=x を含む。

次に例を示す。


class Test {

	public static void main(String[] args) {

		// An example of overflow:
		double d = 1e308;
		System.out.print("overflow produces infinity: ");
		System.out.println(d + "*10==" + d*10);

		// An example of gradual underflow:
		d = 1e-305 * Math.PI;
		System.out.print("gradual underflow: " + d + "\n      ");
		for (int i = 0; i < 4; i++)
			System.out.print(" " + (d /= 100000));
		System.out.println();

		// An example of NaN:
		System.out.print("0.0/0.0 is Not-a-Number: ");
		d = 0.0/0.0;
		System.out.println(d);

		// An example of inexact results and rounding:
		System.out.print("inexact results with float:");
		for (int i = 0; i < 100; i++) {
			float z = 1.0f / i;
			if (z * i != 1.0f)
				System.out.print(" " + i);
		}
		System.out.println();

		// Another example of inexact results and rounding:
		System.out.print("inexact results with double:");
		for (int i = 0; i < 100; i++) {
			double z = 1.0 / i;
			if (z * i != 1.0)
				System.out.print(" " + i);
		}
		System.out.println();

		// An example of cast to integer rounding:
		System.out.print("cast to int rounds toward 0: ");
		d = 12345.6;
		System.out.println((int)d + " " + (int)(-d));
	}
この例は,次の出力を生成する。


overflow produces infinity: 1.0e+308*10==Infinity
gradual underflow: 3.141592653589793E-305
	3.1415926535898E-310 3.141592653E-315 3.142E-320 0.0
0.0/0.0 is Not-a-Number: NaN
inexact results with float: 0 41 47 55 61 82 83 94 97
inexact results with double: 0 49 98
cast to int rounds toward 0: 12345 -12345 
この例は,緩やかなアンダフローが緩やかな精度の損失を生じる可能性があることを示す。

i0 のときの不正確な結果は,ゼロによる除算を含む。そこで, z は正の無限大となり,z * 0 はNaNとなる。1.0に等しくはならない。

4.2.5 boolean型 及び boolean

booleanは,リテラル true 及び false(3.10.3)で示す二つの可能な値をもつ論理的な量を表す。論理演算子には,次の種類がある。

論理式は,いくつかの種類の文において制御フローを決定する。

boolean 式はまた,条件演算子 ? : (15.24)において,どの副文を評価するかを決定する。

boolean 式だけが,条件演算子 ? : の最初のオペランド,及び制御フロー文内で使用できる。任意の非ゼロ値が true となるC言語の慣習に従い,整数 x は,式 x!=0 によって boolean に変換できる。null でない任意の参照が true となるC言語の慣習に従い,オブジェクト参照 obj は,式 obj!=null によって boolean に変換できる。

boolean 値の型 boolean へのキャストは許される(5.1.1)。型 boolean に関する他のキャストは許されない。boolean 値は,文字列変換(5.4)によって文字列に変換できる。

4.3 参照型及び値

参照型(reference types) には,3種類の型,クラス型(8.),インタフェース型(9.)及び配列型(10.)が存在する。

名前は,6.で規定する。型名は,6.5,特に6.5.4で規定する。

次に例を示す。


class Point { int[] metrics; }
interface Move { void move(int deltax, int deltay); } 
この例は,クラス型 Point 及びインタフェース型 Move を宣言し,クラス Point のフィールド metrics を宣言するために,配列型 int[]int の配列)を使用する。

4.3.1 オブジェクト

オブジェクト(object) は,クラスインスタンス(class instance) 又は配列に分かれる。

参照値(しばしば単に 参照(references) と呼ぶ)は,オブジェクトへの ポインタ(pointers) もしくは,いかなるオブジェクトも参照しない特別な空参照となる。

クラスインスタンスは,クラスインスタンス生成式(15.8)又はクラス Class(20.3.8)のメソッド newInstance を呼び出すことによって,明示的に生成される。配列は,配列生成式(15.8)によって明示的に生成される。

式において文字列連結演算子 + (15.17.1)を使用するときは,新しいクラスインスタンスが暗黙のうちに生成され,結果として型 String(4.3.320.12)の新しいオブジェクトとなる。新しい配列オブジェクトは,配列初期化式(10.6)を評価するときに,暗黙のうちに生成される。これは,クラス又はインタフェースを初期化する(12.4)とき,クラスの新しいインスタンスを生成する(15.8)とき,又は局所変数宣言文を実行する(14.3)ときに発生する。

これらの場合を次の例で示す。


class Point {
	int x, y;
	Point() { System.out.println("default"); }
	Point(int x, int y) { this.x = x; this.y = y; }

	// A Point instance is explicitly created at class initialization time:
	static Point origin = new Point(0,0);

	// A String can be implicitly created by a + operator:
	public String toString() {
return "(" + x + "," + y + ")";
} }
class Test { public static void main(String[] args) { // A Point is explicitly created using newInstance: Point p = null; try { p = (Point)Class.forName("Point").newInstance(); } catch (Exception e) { System.out.println(e); }
// An array is implicitly created by an array constructor: Point a[] = { new Point(0,0), new Point(1,1) };
// Strings are implicitly created by + operators: System.out.println("p: " + p); System.out.println("a: { " + a[0] + ", "
+ a[1] + " }");
// An array is explicitly created by an array creation expression: String sa[] = new String[2]; sa[0] = "he"; sa[1] = "llo"; System.out.println(sa[0] + sa[1]); }
この例は,次の出力を生成する。


default
p: (0,0)
a: { (0,0), (1,1) }
hello 
オブジェクトへの参照に対する演算子には,次の種類がある。

同じオブジェクトへの参照は,複数存在してもよい。ほとんどのオブジェクトは,クラスのインスタンスであるオブジェクトのフィールド又は配列オブジェクトの構成要素である変数に,状態を記憶する。二つの変数があり,同じオブジェクトへの参照を保持していれば,オブジェクトの状態は,一方の変数の参照を使って変更できる。その変更した状態を,もう一方の変数の参照により観察できる。

次に例を示す。

class Value { int val; } 

class Test {
	public static void main(String[] args) {
		int i1 = 3;
		int i2 = i1;
		i2 = 4;
		System.out.print("i1==" + i1);
		System.out.println(" but i2==" + i2);
		Value v1 = new Value();
		v1.val = 5;
		Value v2 = v1;
		v2.val = 6;
		System.out.print("v1.val==" + v1.val);
		System.out.println(" and v2.val==" + v2.val);
	}
この例は,次を出力する。


i1==3 but i2==4
v1.val==6 and v2.val==6 
これは,v1.val 及び v2.valnew 式だけによって生成された一つのオブジェクト Value 内で同じインスタンス変数(4.5.3) を参照していることによる。一方,i1 及び i2 は,別々の変数である。

配列の生成及び使用の例は,10 及び 15.9 を参照すること。

個々のオブジェクトは,対応したロック(17.13)をもつ。これは,多重スレッド(17.1220.20)による状態への同時アクセスを制御するために,同期メソッド(8.4.3)及び同期文(14.17)で使用する。

4.3.2 クラス Object

標準のクラス Object は,すべての他のクラスのスーパクラス(8.1)となる。型 Object の変数は,それがクラスのインスタンスか,配列(10.)のインスタンスかにかかわらず,任意のオブジェクトへの参照をもつことができる。すべてのクラス及び配列型は,クラス Object のメソッドを継承する。これについては,ここで概要を示し,20.1で完全に規定する。

package java.lang; 

public class Object {
	public final Class getClass() { . . . }
	public String toString() { . . . }
	public boolean equals(Object obj) { . . . }
	public int hashCode() { . . . }
	protected Object clone()
		throws CloneNotSupportedException { . . . }
	public final void wait()
throws IllegalMonitorStateException,
InterruptedException { . . . } public final void wait(long millis) throws IllegalMonitorStateException, InterruptedException { . . . } public final void wait(long millis, int nanos) { . . . } throws IllegalMonitorStateException, InterruptedException { . . . } public final void notify() { . . . } throws IllegalMonitorStateException public final void notifyAll() { . . . } throws IllegalMonitorStateException protected void finalize() throws Throwable { . . . }
Object のメンバには,次のものがある。

4.3.3 クラス String

クラス String(20.12)のインスタンスは,Unicode文字列を表す。オブジェクト String は,定数(変更されない)値をもつ。文字列リテラル(3.10.5)は, クラス Stringのインスタンスを参照する。

文字列連結演算子 +(15.17.1)は,新しいオブジェクト String を暗黙のうちに生成する。

4.3.4 参照型の同一条件

次の条件を満たすとき,二つの参照型を同じ型(same type) と呼ぶ。

4.4 型の使用場所

型は,宣言又は特定の式で使用する。

一つの型の様々な種類の使用例を次に示す。


import java.util.Random;

class MiscMath {

int divisor;
MiscMath(int divisor) { this.divisor = divisor; }
float ratio(long l) { try { l /= divisor; } catch (Exception e) { if (e instanceof ArithmeticException) l = Long.MAX_VALUE; else l = 0; } return (float)l; }
double gausser() { Random r = new Random(); double[] val = new double[2]; val[0] = r.nextGaussian(); val[1] = r.nextGaussian(); return (val[0] + val[1]) / 2; }
この例では,次の宣言で型が使用される。

さらに次の種類の式で型が使用される。

4.5 変数

変数は,記憶域の位置を示し,プリミティブ型(4.2)又は参照型(4.3)コンパイル時の型(compile-time type) とも呼ばれる型をもつ。変数は,常に,その型と代入互換(5.2)な値を含む。変数の値は,代入(15.25)又は接頭若しくは接尾の ++(増分)若しくは--(減分)演算子(15.13.215.13.315.14.115.14.2)によって変更される。

変数の値とその型との互換性は,Java言語設計が保証する。デフォルト値は互換的(4.5.4)であって,変数へのすべての代入は,代入互換性(5.2)を,通常はコンパイル時に検査される。ただし,配列が関係する場合に限り,実行時検査を実行する(10.10)

4.5.1 プリミティブ型の変数

プリミティブ型の変数は,常にその正確なプリミティブ型の値を保持する。

4.5.2 参照型の変数

参照型の変数は,次のいずれかを保持できる。

4.5.3 変数の種類

変数には,次の7種類が存在する。

  1. クラス変数(class variable) は,クラス宣言(8.3.1.1)の中にキーワードstaticを使用して宣言したフィールド,又はインタフェース宣言(9.3)の中でキーワードstaticを使用若しくは使用しないで宣言したフィールドを言う。クラス変数は,そのクラス又はインタフェースを,ロードした(12.2)ときに生成され,デフォルト値(4.5.4)に初期化される。クラス変数は,そのクラス又はインタフェースをアンロードした(12.8)とき,そのクラス又はインタフェース(12.6)のすべての必要な終了処理を完了した後に,実質的にその存在を終了する。
  2. インスタンス変数(instance variable) は,クラス宣言の中に,キーワードstatic(8.3.1.1)を使用しないで宣言したフィールドを言う。クラス T がインスタンス変数フィールド a をもてば, T 又は T (8.1.3)のサブクラスのオブジェクトを新しく生成したとすると,新たなインスタンス変数 a がオブジェクトの一部として生成され,デフォルト値(4.5.4)が,初期値として設定される。インスタンス変数は,それがフィールドとなっているオブジェクトが参照されなくなったとき,そのオブジェクト(12.6)のすべての必要な終了処理を完了した後に,実質的にその存在を終了する。
  3. 配列構成要素(Array components) は,新しい配列オブジェクトが生成される(15.9)ときに常に生成される名前なし変数で,デフォルト値(4.5.4)に初期化される。配列構成要素は,その配列を参照しなくなったときに,実質的にその存在を終了する。配列の規定については,10を参照すること。
  4. メソッド仮引数(Method parameters) (8.4.1)は,メソッドに渡す実引数の値を保持する。メソッドを呼び出す(15.11)たびに,そのメソッド宣言に宣言した個々の仮引数用に,新しい仮引数変数が生成される。この新しい変数は,メソッド呼出しの対応する実引数の値を初期値とする。メソッド仮引数は,そのメソッドの本体の実行が完了したときに,実質的にその存在を終了する。
  5. コンストラクタ仮引数(Constructor parameters) (8.6.1)は,コンストラクタに渡す実引数の値を保持する。クラスインスタンス生成式(15.8)又は明示的なコンストラクタ呼出し(8.6.5)が,コンストラクタを呼び出すたびに,そのコンストラクタ宣言で宣言した個々のパラメタ用に,新しい仮引数変数が生成される。この新しい変数は,生成式又はコンストラクタ呼出しの対応する実引数の値に初期化される。コンストラクタ仮引数は,そのコンストラクタの本体の実行が完了したときに,実質的にその存在を終了する。
  6. 例外ハンドラ仮引数(exception-handler parameter) は,try文(14.18)catch 節によって例外が捕捉されるたびに生成される。この新しい変数は,その例外(11.314.16)に対応した実際のオブジェクトを初期値とする。例外ハンドラ仮引数は,catch 節によるブロックの実行が完了したときに,実質的にその存在を終了する。
  7. 局所変数(Local variables) は,局所変数宣言文(14.3)で宣言する。制御の流れがブロック(14.2)又はfor文(14.12)に入ったときにいつでも,そのブロック又はfor文内に直接含まれている局所変数宣言文で宣言した個々の局所変数用に,新しい変数が生成される。局所変数宣言文は,その変数を初期設定する式を含んでもよい。しかしながら,初期化式をもつ局所変数は,それを宣言している局所変数宣言文が実行されるまで,初期化されない。(確実な代入の規則(16.)は,局所変数の値が,それが初期化されるか又は別途値が代入される以前に使用されることを防止する。) 局所変数は,ブロック又はfor文の実行が完了したときに,実質的にその存在を終了する。
次の例は,いくつかの違った種類の変数を含む。


class Point {
	static int numPoints;		// numPoints is a class variable
	int x, y;			// x and y are instance variables
	int[] w = new int[10];		// w[0] is an array component
	int setX(int x) {			// x is a method parameter
		int oldx = this.x;	// oldx is a local variable
		this.x = x;
		return oldx;
	}

4.5.4 変数の初期の値

Javaプログラムのすべての変数は,その値が使用される前に,値をもっていなければならない。

次に例を示す。


class Point {
	static int npoints;
	int x, y;
	Point root;
}

class Test { public static void main(String[] args) { System.out.println("npoints=" + Point.npoints); Point p = new Point(); System.out.println("p.x=" + p.x + ", p.y=" + p.y); System.out.println("p.root=" + p.root); }
この例は,次を出力する。


npoints=0
p.x=0, p.y=0
p.root=null 
これは,クラス Point を準備するとき(12.3.2)に発生する npoints のデフォルト初期化,並びに新しい Point を実体化するときに発生する xy 及び root のデフォルト初期化を示している。クラス及びインタフェースのロード,リンク及び初期化に関するあらゆる面の詳細な規定,並びに新しいクラスインスタンスを生成するためのクラスの実体化の規定については,12.を参照のこと。

4.5.5 変数の型及びオブジェクトのクラス

すべてのオブジェクトは,次に示すある特定のクラスに属する。つまり,そのオブジェクトを生成した生成式で言及したクラス,そのオブジェクトを生成するためにメソッド newInstance(20.3.6)の呼出しで使用したオブジェクトのクラス,又は文字列連結演算子 + (15.17.1)によって暗黙に生成されたオブジェクト用の Stringクラス,のどれかに属する。このクラスを,そのオブジェクトのクラス(class of the object) と呼ぶ。(この節の最後で規定するとおり,配列もまたクラスをもつ。)オブジェクトは,そのクラス及びそのクラスのすべてのスーパクラスのインスタンスであるという。

備考 変数又は式が“実行時型をもつ”ということがある。しかし,これは用語の正しい使い方ではない。これは,実行時における変数又は式の値が null でないと仮定して,その値によって参照されるオブジェクトのクラスのことを言及している。正確には,型はコンパイル時の概念で,変数又は式が型をもつ。しかし,オブジェクト又は配列は,型をもたず,クラスに属する。

変数の型は常に宣言されており,式の型はコンパイル時に推論できる。型は,その変数がもつことができる値,又は実行時に式が生成することができる値を制限する。変数の実行時の値が null でない参照ならば,その変数値は,オブジェクト又は配列を参照する。そのオブジェクト又は配列は,クラス(型ではない)をもつ。そのクラスは,必然的にコンパイル時の型と互換性をもつ。

変数又は式は,インタフェース型のコンパイル時型をもつ。インタフェースのインスタンスそのものは存在しない。インタフェース型をもつ変数又は式は,そのインタフェースを実装した(8.1.4)クラスの任意のオブジェクトを参照できる。

次に,新しいオブジェクトを生成し,変数の型とオブジェクトのクラスとの違いを示す例を与える。


public interface Colorable {
	void setColor(byte r, byte g, byte b);
}

class Point { int x, y; } class ColoredPoint extends Point implements Colorable {
byte r, g, b;
public void setColor(byte rv, byte gv, byte bv) { r = rv; g = gv; b = bv; }
}
class Test { public static void main(String[] args) { Point p = new Point(); ColoredPoint cp = new ColoredPoint(); p = cp; Colorable c = cp; }
この例は,次のことを示している。

すべての配列も又クラスをもつ。メソッド getClass(20.1.1)は,配列オブジェクトに対して呼び出したときは,配列のクラスを表す(クラス Class の)クラスオブジェクトを返す。配列用のクラスは,Java識別子ではない独特な名前をもつ。例えば,構成要素が int の配列のクラスは,"[I" という名前をもち,したがって,式

new int[10].getClass().getName() 
の値は,文字列 "[I" となる。詳細は,20.1.1を参照すること。


目次 | |