初めに
配列の初期化にはいくつかルールがあり、非常に間違えやすい。まとめたので、1つ1つ理解していこう。
配列の宣言
[]はデータ型の後でも変数名の後でもどちらでもok。この時[]の中身は何も書かない。
int[] array1;
int array2[];
配列のサイズの指定
以下では1次元配列に3つの要素を入れる箱を作っている。この時、new側の[]に要素数を入れるのが必須。忘れるとエラーになるので注意。
int[] array1;
array1 = new int[3];
int[] array2 = new int[3];
int[][] array3 = new int[2][];
int[] array4[] = new int[2][]
NG集
int[] array1 = new int[]; //要素数が未指定
int[][] array2 = new int[2]; //宣言した配列と配列のサイズがずれている
配列の初期化
int[] array1;
array1 = new int[3];
array1[0] = 1;
array1[1] = 3;
array1[2] = 3;
int[] array2 = new int[2]{1,2,3};
int[][] array3 = new int[][]{}; //{}は空でも良い
int[] array4 = {1,2,3};
NG集
int[] array1 = new int[2]{} //配列初期子がある場合、[]の要素数は記載できない
int[] array2 = new int[3];
array2 = {1,2,3} //配列初期子はnew int[]を使う初期化の時のみ使用可能
クラスを配列で扱う時の注意点
public class A{
public int a;
}
public class Main {
public static void main(String[] args) {
A[] arrayA = new A[2];
for(A array : arrayA) {
System.out.println(array.a);
}
}
}
結果
Exception in thread "main" java.lang.NullPointerException: Cannot read field "a" because "array" is null
at Main.main(Main.java:5)
ここで注意すべきなのは配列を宣言・サイズを指定したのみで、配列に含まれるクラスをインスタンス化していないということだ。そのため、インスタンス変数は初期化されずnullの状態でfor文に使われようとしたため例外が発生している。
もしインスタンス変数を初期化した状態で配列にしたければ、配列の初期化時にインスタンス化しておくと良い。なおこれはインスタンス変数のみでクラス変数(static変数)はインスタンス化しなくても使えるので、上記のソースで問題無く呼び出せる。
public class Main {
public static void main(String[] args) {
A[] arrayA = new A[] {new A(),new A()};//修正
for(A array : arrayA) {
System.out.println(array.a);
}
}
}
結果
0
0
配列の型について
以下の問題を考えてみよう。
public class Sample{
public void test(Object[] val) {
System.out.println("Object[]");
}
public void test(Object val) {
System.out.println("Object");
}
}
public class Main {
public static void main(String[] args) {
new Sample().test(new int[3]);
}
}
結果
Object
これはnew int[3]がObject型としてとらえられていることを意味する。今回完全一致する引数はないが、そのメソッドを呼び出しているコードがコンパイルで型変換され、対応するメソッドで呼び出すようになる。この時配列はObjectクラスのサブクラスであることを覚えておくこと。一方Object型の配列は参照の集合を扱う配列のため、new int[3]のような値の集合を扱う配列とは異なる型になる。
String型配列とint型配列の初期値
public class Main {
public static void main(String[] args) {
int[] nums = new int[3];
String[] strs = new String[3];
for(int num : nums) {
System.out.println(num);
}
for(String str : strs) {
System.out.println(str);
}
}
}
結果
0
0
0
null
null
null
上記を実施するとString型配列の要素の初期値はnull、int型配列の要素の初期値は0となる。
まとめ
- 配列の宣言は[]を使う
- 配列のサイズの指定はnew側の[]に要素数を入れる
- 配列の初期化では配列初期子{}を使う。なお、配列初期子がある場合、[]の要素数は記載できない。また、配列初期子はnew int[]を使う時のみ使用可
- クラスを配列に含める場合、インスタンスの初期化も忘れずに
- 配列はObjectクラスのサブクラスに含まれる
- String型配列の初期値はnull、int型配列の初期値は0