Java言語の型は,二つのカテゴリ,プリミティブ型及び参照型に分けられる。プリミティブ型(4.2)は,
boolean型(論理型)及び数値型に分ける。数値型は,整数的な型である
byte,short,int,long 及び
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
の変数は,空参照又はクラスインスタンス若しくは配列の任意のオブジェクトへの参照を,保持する。
Type:
PrimitiveType
ReferenceType
null の型である特別な 空型(null
type)
も存在する。それには名前がない。空型には名前がないので,空型の変数を宣言すること又は空型にキャストすることはできない。空型の式が取りうる唯一の値が空参照となる。 空参照は,常に任意の参照型にキャストできる。実際には,Javaプログラマは,空型を無視し,空型は任意の参照型となれる単なる特別なリテラルであると見なしても良い。
PrimitiveType:プリミティブ値は,他のプリミティブ値と状態を共有しない。型をプリミティブ型とする変数は,常にそれと同じ型のプリミティブ値を保持する。プリミティブ型の変数の値は,その変数に対する代入演算によってだけ変更できる。
NumericType
booleanNumericType:
IntegralType
FloatingPointType IntegralType: one of
byte short int long charFloatingPointType: one of
float double
数値型(numeric types) は,整数的な型及び浮動小数点型とする。
整数的な型(integral types)
は,byte,short,int 及び
long(それぞれ,8ビット,16ビット,32ビット及び64ビットの2の補数符号付き整数),並びに
char(Unicode文字を表す16ビット符号無し整数)に分ける。
浮動小数点型(floating-point types)
は,float(32ビットIEEE 754浮動小数点数)及び double(64ビットIEEE
754浮動小数点数)とする。
型 boolean
は二つの値,true(真)及びfalse(偽),だけをとる。
byte -128以上,127以下。
short -32768以上,32767以下。
int -2147483648以上,2147483647以下。
long -9223372036854775808以上,9223372036854775807以下。
char '\u0000' 以上,'\uffff'
以下,すなわち,0以上,65535以下。
boolean の値になる。
int 又は型 long になる。
+ 及び - (15.14.3,15.14.4)。
*,/ 及び % (15.16)。
+ 及び - (15.17.2)。
++,接頭語(15.14.1)及び接尾語(15.13.2)の両方。
--,接頭語(15.14.2)及び接尾語(15.13.3)の両方。
<<,>> 及び
>>> (15.18)。
~ (15.14.5)。
&,| 及び ^ (15.21.1)。 ? : (15.24)。
+ (15.17.1)。String
オペランド及び整数的オペランドを与えたとき,整数的オペランドをその値を表す10進数表記のString に変換し,次にその二つの
String を連結した新しい文字列を生成する。 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 の間では,キャストはできない。
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 は, +1又は -1,m は,
未満の正整数とし,e は, -149 以上 104 以下の整数とする。m
が正であるが
未満であって,e が -149
に等しい形式の値を,非正規化(denormalized) されているという。
型 double の有限非ゼロ値の形式は,
とする,ここで s は, +1 又は -1,m は,
未満の正整数であり,e は, -1075 以上 970 以下の整数とする。m
が正であって
未満及び 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!=x は
true を, x 又は y がNaNならば,(x<y)
==!(x>=y) は false を返す。
浮動小数点型の任意の値は,任意の数値型へキャストしてよい。又は任意の数値型からキャストされてもよい。浮動小数点型と型
boolean との間では,キャストできない。
boolean の値になる。
float 又は型 double になる。
+ 及び - (15.14.3,15.14.4参照)。
*,/ 及び % (15.16)。
+ 及び - (15.17.2)。
++,接頭語(15.14.1)及び接尾語(15.13.2)の両方。
--,接頭語(15.14.2)及び接尾語(15.13.3)の両方。 ? : (15.24)。
+ (15.17.1)。String
オペランド及び浮動小数点オペランドを与えたとき,浮動小数点オペランドを,その値を表す10進表現の文字列に情報の損失無しに変換し,次にそれら二つの文字列を連結した新しいString
を生成する。 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この例は,緩やかなアンダフローが緩やかな精度の損失を生じる可能性があることを示す。
i が 0 のときの不正確な結果は,ゼロによる除算を含む。そこで,
z は正の無限大となり,z * 0
はNaNとなる。1.0に等しくはならない。
boolean型 及び boolean値booleanは,リテラル true 及び false(3.10.3)で示す二つの可能な値をもつ論理的な量を表す。論理演算子には,次の種類がある。
== 及び != (15.20.2)。
! (15.14.6)。
&,^ 及び | (15.21.2)。
&& (15.22)及び || (15.23)。
? : (15.24)。
+(15.17.1)。String
オペランド及び論理オペランドを与えたとき,論理オペランドを
String("true" 又は
"false")に変換し,それから,二つの文字列を連結した新しい String
を生成する。
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)によって文字列に変換できる。
ReferenceType:名前は,6.で規定する。型名は,6.5,特に6.5.4で規定する。
ClassOrInterfaceType
ArrayType ClassOrInterfaceType:
ClassType
InterfaceType ClassType:
TypeName InterfaceType:
TypeName ArrayType:
Type[ ]
この例は,クラス型
class Point { int[] metrics; }
interface Move { void move(int deltax, int deltay); }
Point 及びインタフェース型 Move
を宣言し,クラス Point のフィールド metrics を宣言するために,配列型
int[](int の配列)を使用する。
参照値(しばしば単に 参照(references) と呼ぶ)は,オブジェクトへの ポインタ(pointers) もしくは,いかなるオブジェクトも参照しない特別な空参照となる。
クラスインスタンスは,クラスインスタンス生成式(15.8)又はクラス Class(20.3.8)のメソッド newInstance
を呼び出すことによって,明示的に生成される。配列は,配列生成式(15.8)によって明示的に生成される。
式において文字列連結演算子 + (15.17.1)を使用するときは,新しいクラスインスタンスが暗黙のうちに生成され,結果として型
String(4.3.3,20.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 オブジェクトへの参照に対する演算子には,次の種類がある。
+ (15.17.1)。これは,String
オペランドと参照を与えたとき,その参照を,参照されたオブジェクトのメソッド toString(20.1.2)を呼び出すことによって,Stringに変換する(その参照又は
toString
の結果が空参照なら"null"を使う)。それから,二つの文字列を連結した新しいString
を生成する。
instanceof 演算子(15.19.2)。
== 及び != (15.20.3)。
? : (15.24)。 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.val が new
式だけによって生成された一つのオブジェクト Value 内で同じインスタンス変数(4.5.3) を参照していることによる。一方,i1 及び
i2 は,別々の変数である。
配列の生成及び使用の例は,10 及び 15.9 を参照すること。
個々のオブジェクトは,対応したロック(17.13)をもつ。これは,多重スレッド(17.12,20.20)による状態への同時アクセスを制御するために,同期メソッド(8.4.3)及び同期文(14.17)で使用する。
ObjectObject は,すべての他のクラスのスーパクラス(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
のメンバには,次のものがある。
getClass は,そのオブジェクトのクラスを表すオブジェクト Class (20.3)を返す。オブジェクト
Classは,個々の参照型のために存在する。例えば,それは,クラスの完全限定名,そのメンバ,その直上のスーパクラス及びそれが実装するすべてのインタフェース,を見つけるために使用できる。synchronized
(8.4.3.5)と宣言しているクラスメソッドは,そのクラスのオブジェクト
Class と対応したロックを同期化する。
toString は,そのオブジェクトの文字列表現を返す。
equals 及びメソッド hashCode
は,java.util.Hashtable (21.7)などのハッシュ表を利用するために宣言する。メソッド
equals は,オブジェクト等価の概念を定義する。これは,参照ではなく値の比較に基づく。
clone は,オブジェクトの複製を作るために使用する。
wait,notify 及び notifyAll
は,17.で規定しているとおり,スレッドを使った並行プログラミングで使用する。
finalize は,オブジェクトを破壊する直前に実行するものであり,(12.6)に規定している。 StringString(20.12)のインスタンスは,Unicode文字列を表す。オブジェクト
String は,定数(変更されない)値をもつ。文字列リテラル(3.10.5)は, クラス Stringのインスタンスを参照する。
文字列連結演算子 +(15.17.1)は,新しいオブジェクト String を暗黙のうちに生成する。
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;
}
} この例では,次の宣言で型が使用される。
java.util の型 java.util.Random からインポートされた型
Random が宣言される。
MiscMath のフィールド
divisor を,型 int で宣言する。
ration
の仮引数 l を,型 long で宣言する。
ratio
の結果が型 float で,メソッド gausser の結果が型
double で宣言される。
MiscMath
に対するコンストラクタの仮引数を型 int で宣言する。
gausser の局所変数
r 及び val が,型 Random 及び型
double[] (double の配列)で宣言される。
catch
節の例外ハンドラ仮引数 e が型 Exception で宣言される。
gausser の局所変数 r が,型 Random
を使ったクラスインスタンス生成式によって初期化される。
gausser
の局所変数 val が,大きさ2の double の配列を生成する配列生成式によって初期化される。
ratioreturn 文が,キャストで型 float を使用する。
instanceof 演算子 (15.19.2)。instanceof
演算子が,e を型 ArithmeticException と代入互換かどうか試験する。
++(増分)若しくは--(減分)演算子(15.13.2,15.13.3,15.14.1,15.14.2)によって変更される。
変数の値とその型との互換性は,Java言語設計が保証する。デフォルト値は互換的(4.5.4)であって,変数へのすべての代入は,代入互換性(5.2)を,通常はコンパイル時に検査される。ただし,配列が関係する場合に限り,実行時検査を実行する(10.10)。
T
がインスタンス変数フィールド a をもてば, T 又は
T (8.1.3)のサブクラスのオブジェクトを新しく生成したとすると,新たなインスタンス変数 a がオブジェクトの一部として生成され,デフォルト値(4.5.4)が,初期値として設定される。インスタンス変数は,それがフィールドとなっているオブジェクトが参照されなくなったとき,そのオブジェクト(12.6)のすべての必要な終了処理を完了した後に,実質的にその存在を終了する。
catch
節によって例外が捕捉されるたびに生成される。この新しい変数は,その例外(11.3,14.16)に対応した実際のオブジェクトを初期値とする。例外ハンドラ仮引数は,catch
節によるブロックの実行が完了したときに,実質的にその存在を終了する。
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;
}
}
byte については,デフォルト値はゼロ,すなわち (byte)0 とする。
short については,デフォルト値はゼロ,すなわち (short)0 とする。
int については,デフォルト値はゼロ,すなわち 0 とする。
long については,デフォルト値はゼロ,すなわち 0L とする。
float については,デフォルト値は正のゼロ,すなわち 0.0f とする。
double については,デフォルト値は正のゼロ,すなわち 0.0d とする。
char については,デフォルト値は空文字,すなわち '\u0000' とする。
boolean については,デフォルト値は false とする。
null とする。
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 を実体化するときに発生する
x,y 及び root
のデフォルト初期化を示している。クラス及びインタフェースのロード,リンク及び初期化に関するあらゆる面の詳細な規定,並びに新しいクラスインスタンスを生成するためのクラスの実体化の規定については,12.を参照のこと。
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;
}
} この例は,次のことを示している。
Test のメソッド main の局所変数 p は,型
Point をもち,クラス Point の新しいインスタンスへの参照が初期値として代入される。
cp は,型 ColoredPoint をもち,クラス
ColoredPoint の新しいインスタンスへの参照が初期値として代入される。
cp の値の変数 p への代入によって,p は,オブジェクト
ColoredPoint への参照を保持する。これは,ColoredPoint が
Point のサブクラスなので許される。そこで,クラス ColoredPoint は,型
Point と代入互換となる(5.2)。オブジェクト
ColoredPoint は, Point
のすべてのメソッドに対する支援を含む。ColoredPoint 固有のフィールド
r,g 及び b に加えて,クラス Point
のフィールド,すなわち,x 及び y ももつ。
c は,その型として,インタフェース型 Colorable
をもつ。そこで,Colorable
を実装するクラスのいかなるオブジェクトへの参照も保持できる。特に,ColoredPoint の参照を保持できる。
new
Colorable()”などの式は意味がない。これは,インタフェースのインスタンスは生成できず,クラスのインスタンスだけが生成可能なためである。
getClass(20.1.1)は,配列オブジェクトに対して呼び出したときは,配列のクラスを表す(クラス
Class の)クラスオブジェクトを返す。配列用のクラスは,Java識別子ではない独特な名前をもつ。例えば,構成要素が
int の配列のクラスは,"[I" という名前をもち,したがって,式
new int[10].getClass().getName()の値は,文字列
"[I" となる。詳細は,20.1.1を参照すること。