目次 | 前 | 次 | 索引 | 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[]
は,同じ配列となっている。
Class
Class
オブジェクトをもち,このオブジェクトを同じ構成要素型をもつすべての他の配列と共有する。配列型の直接的上位クラスは,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版 |