| 目次 | 前 | 次 | 索引 | Java言語規定 第2版 |
Javaプログラム言語における 配列(arrays) は,オブジェクト(4.3.1)とし,動的に生成され,型 Object(4.3.2)の変数に代入してよい。すべてのクラスObject のメソッドは,配列に対して呼び出してよい。
配列オブジェクトは,多くの変数を含む。変数の数はゼロであってもよい。この場合,その配列は空(empty)という。配列に含まれる変数は,名前をもたない。その代わりに,負でない整数インデクス値を用いる配列アクセス式で参照する。これらの変数は,配列の構成要素(component)と呼ぶ。配列が n個の構成要素をもてば,n を配列の長さとする。配列の構成要素は,0から n- 1までの整数インデクスを使用して参照する。
配列の構成要素はすべて,配列の 構成要素型(component type)と呼ぶ同じ型をもつ。配列の構成要素型がT ならば,その配列自体の型をT[] とする。
型floatの配列の構成要素の値は,常に単精度数値集合(4.2.3)の要素とする。同様に,型doubleの配列の構成要素の値は常に倍精度数値集合の要素とする。型floatの配列構成要素の値が,単精度数値集合の要素ではない単精度指数部拡張数値集合の要素であることと,型doubleの配列構成要素の値が,倍精度数値集合の要素ではない倍精度指数部拡張数値集合の要素であることは許されない。
配列の構成要素型は,それ自体が配列の型となってもよい。その配列の構成要素は,下位配列への参照を含んでもよい。任意の配列型から始めて,その構成要素を考え,構成要素も配列型ならばその構成要素を考え,などとしていったときに,いつかは配列型ではない構成要素型に到達しなければならない。この型を元の配列の要素型(element type)と呼び,データ構造のこのレベルの構成要素を,元の配列の 要素(element)と呼ぶ。
配列の要素を配列とできる状況が幾つか存在する。要素の型が Object又はCloneable又はjava.io.Serializableならば,要素の幾つか又はすべてが配列であってよい。これは,任意の配列オブジェクトをそれらの型の変数に代入可能であることによる。
[]を続けて書く。角括弧対の数は,配列の入れ子の深さを示す。配列の長さは,その型の一部とはしない。
配列の要素型は,基本型又は参照型の任意の型であってよい。特に次のとおりとする。
abstractなクラス型をもつ配列を許す。このような配列の要素は,その値として,空参照又はabstractなクラスの下位クラスであって、それ以外はabstractではないクラスのインスタンスをもってよい。
配列の長さは,その型の一部分とはしないので,配列型の一つの変数が異なった長さの配列への参照を含んでもよい。
配列オブジェクトを生成する配列変数の宣言の例を次に示す。int[] ai; // array of int short[][] as; // array of array of short Object[] ao, // array of Object otherAo; // array of Object short s, // scalar short aas[][]; // array of array of short
Exception ae[] = new Exception[3];
Object aao[][] = new Exception[2][3];
int[] factorial = { 1, 1, 2, 6, 24, 120, 720, 5040 };
char ac[] = { 'n', 'o', 't', ' ', 'a', ' ',
'S', 't', 'r', 'i', 'n', 'g' };
String[] aas = { "array", "of", "String", };
[]は,宣言の最初の部分における型の一部又は特定の変数に対する宣言子の一部,あるいは,その両方として出現してよい。次に例を示す。
この宣言は,次と等価とする。byte[] rowvector, colvector, matrix[];
一度,配列オブジェクトを生成したら,その長さは不変とする。一つの配列変数が異なる長さの配列を参照するためには,異なる配列への参照を変数へ代入しなければならない。byte rowvector[], colvector[], matrix[][];
A を参照型とする場合で,配列変数v が型A[]をもつとき,B をA に代入可能ならば,v は任意の配列型B[]のインスタンスへの参照を保持可能とする。これは,その後の代入において実行時例外を生じるかもしれない。詳細については10.10を参照のこと。
配列生成式は,要素型,入れ子になった配列のレベルの数及び少なくとも一つの入れ子のレベルにおいての配列の長さを指定する。配列の長さは,最終インスタンス変数 length として利用可能とする。
配列初期化子は,配列を生成し,すべての構成要素に初期値を与える。
A[i]のように,配列参照に"["及び"]"で囲ったインデクス式を続けた式で構成される配列アクセス式(15.13)によって,アクセスされる。すべての配列は0を最初の要素とする。長さn の配列は,0からn-1までの整数によってインデクス付け可能とする。
配列は,int値によってインデクス付けしなくてはならない。short,byte又はchar値もインデクス値として使用してよい。これは,これらが単項数値昇格(5.6.1) に従い,int値となることによる。longインデクス値によって配列構成要素をアクセスしようとすると,コンパイル時エラーが結果として起こる。
すべての配列のアクセスは,実行時に検査される。0未満又は配列の長さ以上のインデクスを使用すると,IndexOutOfBoundsExceptionが投げられる。
class Gauss {
public static void main(String[] args) {
int[] ia = new int[101];
for (int i = 0; i < ia.length; i++)
ia[i] = i;
int sum = 0;
for (int i = 0; i < ia.length; i++)
sum += ia[i];
System.out.println(sum);
}
}
これは,次の出力を生成する。
この例は,5050
int の配列,つまり int[]という型をもつ変数ia を宣言している。変数 ia は,配列生成式(15.10)によって生成される新たな配列オブジェクトを参照する。配列生成式は,101個の構成要素をもつと指定する。配列の長さは,示されている通り,フィールドlengthを使って利用可能とする。
このプログラムは,配列を 0 から100までの整数で埋め,これらの整数を合計し,その結果を印刷する。
ArrayInitializer:この記述を明確にするために,再度8.3 の記述を次に示す。{VariableInitializersopt,opt}VariableInitializers: VariableInitializer VariableInitializers,VariableInitializer
VariableInitializer: Expression ArrayInitializer配列初期化子は,式をコンマで区切った並びとして記述し,"
{"及び"}"で囲む。
配列初期化子における式は,ソースコード中に現れる文字順に左から右に実行される。n番目の変数初期化子は,n-1番目の配列構成要素の値を指定する。 各式は,配列の構成要素型と代入互換(5.2)でなければならない。そうでないときには,コンパイル時エラーが生じる。
構成要素型がそれ自体配列型ならば,構成要素を指定する式は,それ自体,配列初期化子であってよい。つまり,配列初期化子は入れ子にしてもよい。
配列初期化子内における最後の式の後に,それに続いてコンマが出現してもよい。このコンマは無視される。
class Test {
public static void main(String[] args) {
int ia[][] = { {1, 2}, null };
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
System.out.println(ia[i][j]);
}
}
これは,途中までは,次を出力する。
ただし,その後,空参照となっている配列1 2
iaの2番目の構成要素にインデクス付けしようとして,NullPointerExceptionが発生する。
public finalなフィールドlength。(lengthは,正又は0であってもよい。)
public なメソッド clone。これは,クラスObject 内の同じ名前のメソッドを上書きし,検査例外を投げない。
Objectから継承されたすべてのメンバ。ただし,唯一メソッド clone だけは継承しない。
これによって,配列は次のクラスと同じ公開フィールドとメソッドをもつ。
class A implements Cloneable, java.io.Serializable {
public final int length = X;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e.getMessage());
}
}
}
すべての配列は,インタフェースCloneable及びjava.io.Serializableを実装する。
class Test {
public static void main(String[] args) {
int ia1[] = { 1, 2 };
int ia2[] = (int[])ia1.clone();
System.out.print((ia1 == ia2) + " ");
ia1[1]++;
System.out.println(ia2[1]);
}
}
これは次を出力する。
これは,false 2
ia1及びia2によって参照される配列の構成要素は,異なった変数であることを示す。(初期のJavaプログラム言語の一部の実装において,この例はコンパイルに失敗した。なぜならばコンパイラは,配列のためのクローンメソッドは,CloneNotSupportedExceptionを投げることができると誤って信じていたからである。)
多次元配列のcloneは浅い。すなわち,レベル一つの新しい配列だけを生成する。下位配列は,共有される。
class Test {
public static void main(String[] args) throws Throwable {
int ia[][] = { { 1 , 2}, null };
int ja[][] = (int[][])ia.clone();
System.out.print((ia == ja) + " ");
System.out.println(ia[0] == ja[0] && ia[1] == ja[1]);
}
}
これは次を出力する。
false true
ia[0] の配列 int[] 及び
ja[0] の配列 int[] は,同じ配列となっている。
ClassClassオブジェクトをもち,このオブジェクトを同じ構成要素型をもつすべての他の配列と共有する。配列型の直接的上位クラスは,Objectとする。すべての配列型は,インタフェースCloneable及びjava.io.Serializableを実装する。
class Test {
public static void main(String[] args) {
int[] ia = new int[3];
System.out.println(ia.getClass());
System.out.println(ia.getClass().getSuperclass());
}
}
これは次を出力する。
ここで,文字列"class [I class java.lang.Object
[I"は,クラスオブジェクト"構成要素型int をもつ配列"に対する,実行時の型シグネチャとする。
char の配列は Stringでなく,'\u0000'(NUL文字)で終わるchar配列も Stringではない。
charの配列は,変化する要素をもつが,オブジェクトStringは不変であって,その内容は決して変化しない。クラスString 内のメソッドtoCharArrayは,Stringと同じ文字の並びを含む文字配列を返す。クラスStringBufferは,文字の変化可能な配列についての役に立つメソッドを実装する。
[]をもつとき,B がA に代入可能ならば,vは任意の配列型B[]のインスタンスへの参照を保持することができる。
class Point { int x, y; }
class ColoredPoint extends Point { int color; }
class Test {
public static void main(String[] args) {
ColoredPoint[] cpa = new ColoredPoint[10];
Point[] pa = cpa;
System.out.println(pa[1] == null);
try {
pa[0] = new Point();
} catch (ArrayStoreException e) {
System.out.println(e);
}
}
}
これは次の出力を生成する。
ここで変数true java.lang.ArrayStoreException
pa は,型 Point[]をもち,変数cpa は,値として型ColoredPoint[]のオブジェクトへの参照値をもつ。ColoredPointは,Pointに代入可能とする。その結果,cpaの値はpaに代入可能とする。
この配列 pa への参照は,例えば,pa[1]がnullかどうかを試験することで,実行時型エラーを生じない。これは,型ColoredPoint[]の配列の要素が ColoredPointであって,PointはColoredPointの上位クラスなので,すべてのColoredPointがPointの代わりとなることが可能であることによる。
一方,配列 paへの代入は,実行時エラーを生じることがある。コンパイル時には,paの要素への代入は,代入された値が確かにPointであることを検査する。しかし,pa がColoredPointの配列への参照を保持しているので,実行時に代入された値の型がColoredPointであるときだけ,代入は有効とする。
Java仮想計算機は,代入が有効であることを保証するために,実行時にこのような状況を検査する。そうでないときには,ArrayStoreExceptionが投げられる。より形式的には次のとおりとする。つまり,Aを参照型とする場合に,型をA[]とする配列の要素への代入は,実際の要素型がAに代入可能な任意の参照型であってよいとき,代入された値が,確かにその配列の実際の要素型へ代入可能なことを保証するために実行時に検査する。
| 目次 | 前 | 次 | 索引 | Java言語規定 第2版 |