配列宣言の全体像
配列は「同じ型の要素を並べて管理する入れ物」です。Java の配列は「長さが固定」「0 始まりの添字」「参照型(配列そのものはオブジェクト)」という3点が基本です。宣言は「型+角括弧+変数名」で行い、必要に応じてサイズ(長さ)や初期値を同時に指定します。
宣言だけ/宣言と生成/宣言と初期化の違い
宣言だけ(まだ何も入っていない)
int[] a; // int の配列「への参照」を宣言。まだ配列は存在しない(null)
String[] s; // String の配列「への参照」
Java「配列変数」は配列オブジェクトへの参照です。宣言だけでは実体がないため、使う前に「生成(new)」が必要です。
宣言して生成(サイズを決める)
int[] a = new int[3]; // 要素数 3 の int 配列を生成(初期値は 0)
String[] s = new String[2]; // 要素数 2 の String 配列(初期値は null)
Javanew 型[長さ] で配列オブジェクトが作られます。「長さは固定」で、後から増減できません。
宣言して初期化(リテラルで値を並べる)
int[] a = {10, 20, 30}; // 要素数は並べた数で決まる
String[] s = {"Java", "is", "fun"};
Java「並べた通りに値が入る」最も読みやすい書き方です。サイズ指定と要素列挙は同時には書けません(new int[3]{...} のような記法は不可)。
重要ポイントの深掘り:型・初期値・長さの不変
型は要素ごとに統一
配列の型は要素の型と一致します。int[] に小数や文字列は入れられません。ラッパー型(Integer[])とプリミティブ(int[])は別物です。
int[] nums = new int[3];
nums[0] = 42; // OK
// nums[1] = "hi"; // NG:型が違う
Javaデフォルト初期値
- 数値(
int,long,doubleなど):0 boolean:false- 参照型(
String,Objectなど):null
boolean[] flags = new boolean[2]; // {false, false}
String[] names = new String[2]; // {null, null}
Java「未代入でも何かは入っている」ため、ヌルチェックと値チェックを使い分けます。
長さは不変(後から増えない)
int[] a = new int[3];
// a.length = 5; // NG:length は読み取り専用
Java増やしたい場合は「新しい配列を作ってコピー」するか、可変長の ArrayList を使いましょう。
宣言位置と書き方のスタイル
推奨スタイル:角括弧は型側
int[] a; // 推奨
// int a[]; // 旧来の記法。意味は同じだが、型側に[]を付けるほうが読みやすい
Javaチーム規約がなければ「型側に []」で統一すると、複合宣言のときにも誤読が減ります。
参照の共有と代入
int[] a = {1, 2};
int[] b = a; // 同じ配列を指す(参照のコピー)
b[0] = 99;
System.out.println(a[0]); // 99(共有しているので両方に見える)
Java「独立したコピー」が必要なら、Arrays.copyOf や clone を使います。
int[] a = {1, 2, 3};
int[] c = a.clone(); // 新しい配列
int[] d = java.util.Arrays.copyOf(a, a.length);
Java多次元配列(配列の配列)
宣言と生成
int[][] m; // 2 次元配列への参照
m = new int[2][3]; // 2 行 3 列(行×列)
m[0][1] = 42;
Java「配列の配列」なので、行ごとに長さを変えるジャグ配列も作れます。
int[][] jag = new int[3][];
jag[0] = new int[1];
jag[1] = new int[2];
jag[2] = new int[4];
Java初期化リテラル
int[][] m = {
{1, 2, 3},
{4, 5, 6}
};
Java行ごとの括弧で「見た目通り」に宣言・初期化できます。
宣言と同時初期化の応用
要素が多い場合の読みやすさ
String[] langs = {
"Java", "Kotlin", "Scala",
"Groovy", "Clojure"
};
Java改行を使って「ひと目で分かる」形にします。保守しやすさが上がります。
new とブロック初期化の組み合わせ(メソッド引数向け)
printAll(new String[] {"A", "B", "C"});
static void printAll(String[] arr) {
for (String s : arr) System.out.println(s);
}
Java「その場で一時配列を作って渡す」パターンは、テストコードやユーティリティに便利です。
よくある落とし穴と対策
Null のまま使って例外
int[] a; // まだ null
// a[0] = 1; // NullPointerException
a = new int[1]; // 生成してから使う
a[0] = 1;
Java「宣言だけでは配列は存在しない」。必ず new か初期化リテラルで生成します。
添字範囲外アクセス
int[] a = {10, 20, 30};
// a[3] = 0; // ArrayIndexOutOfBoundsException(最後は a.length-1)
Javaループ条件は「未満(i < a.length)」を徹底して、オフバイワンを防ぎます。
プリミティブ配列とラッパー配列の取り違え
int[] p = {1, 2}; // プリミティブ
Integer[] w = {1, 2}; // ラッパー(null を持てる、ジェネリクスと相性)
JavaAPI がどちらを要求しているか確認しましょう。List<Integer> とは直接互換ではありません。
実用例で身につける
例 1: 宣言・生成・代入を段階で
public class DeclStep {
public static void main(String[] args) {
int[] scores; // 宣言
scores = new int[3]; // 生成(長さ 3)
scores[0] = 80; // 代入
scores[1] = 90;
scores[2] = 75;
System.out.println(scores[1]); // 90
}
}
Java例 2: 初期化リテラルで一気に
public class InitLiteral {
public static void main(String[] args) {
String[] fruits = {"apple", "banana", "cherry"};
for (int i = 0; i < fruits.length; i++) {
System.out.printf("[%d]=%s%n", i, fruits[i]);
}
}
}
Java例 3: 多次元配列の宣言・初期化
public class Matrix {
public static void main(String[] args) {
int[][] m = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(m[1][2]); // 6
}
}
Java設計の指針(重要部分のまとめ)
- 配列変数は「参照」。宣言だけでは null、使う前に必ず生成(
new)か初期化リテラルで実体化。 - 長さは固定。増やす必要があるなら新しい配列へコピー、頻繁に増減するなら
ArrayListを選ぶ。 - ループの条件は「未満(
i < arr.length)」でオフバイワンを防ぐ。多次元は「配列の配列」として捉える。 - デフォルト初期値(数値0、boolean false、参照 null)を理解し、ヌル扱いと値扱いを正しく設計。
- 参照を共有すると両者に変更が見える。独立性が必要なら
clone/copyOfを使う。
