配列の長さの基礎
Java の配列は「固定長」です。作成時に決めた要素数は後から増減できません。長さはフィールド length で参照し、先頭の添字は 0、最後の添字は length - 1 です。配列の長さを使いこなすことが、境界バグ(オフバイワン)を防ぐ一番の近道になります。
length の使い方と不変性
基本アクセスと読み取り専用であること
int[] a = {10, 20, 30};
System.out.println(a.length); // 3
// a.length = 5; // NG:length は読み取り専用(代入不可)
Javalength は「フィールド」で、メソッドではありません(括弧は付けません)。String の文字数は length() メソッドで、配列と混同しないようにします。
String s = "Java";
System.out.println(s.length()); // 4(配列と違いメソッド)
Javaループ設計と境界(深掘り)
未満条件で安全に走査する
int[] a = {10, 20, 30, 40};
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]); // 0〜length-1 を安全に走査
}
Java終了条件は「未満(<)」が定番です。<= を使うと最後の次を踏んで例外になります。最後の要素にアクセスしたいときは a[a.length - 1] を使います。
逆順走査の定番パターン
String[] words = {"Java", "is", "fun"};
for (int i = words.length - 1; i >= 0; i--) {
System.out.println(words[i]);
}
Java開始は「最後の添字」、終了条件は「0以上」。この形が最も読みやすく、境界を外しにくいです。
多次元配列の長さ(配列の配列)
行と列の長さを正しく参照する
int[][] m = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(m.length); // 行数: 2
System.out.println(m[0].length); // 0行目の列数: 3
System.out.println(m[1].length); // 1行目の列数: 3
Java行ごとの長さが異なるジャグ配列では、必ず「その行の length」を参照します。固定観念で列数を決め打ちすると、範囲外アクセスになります。
int[][] jag = { {1}, {2,3}, {4,5,6} };
for (int r = 0; r < jag.length; r++) {
for (int c = 0; c < jag[r].length; c++) {
System.out.printf("[%d,%d]=%d%n", r, c, jag[r][c]);
}
}
Java0 長配列と null の使い分け(深掘り)
「存在しない」と「空だが有効」を区別する
String[] names = null; // 未初期化(配列そのものがない)
String[] empty = new String[0]; // 要素数 0(配列はある)
JavaAPI 設計では、可能なら「空配列を返す(null にしない)」方が扱いやすくなります。呼び出し側の分岐が減り、length == 0 のチェックだけで済むからです。
長さを変えたいときの安全策
新しい配列を作ってコピーする
import java.util.Arrays;
int[] a = {1, 2, 3};
int[] bigger = Arrays.copyOf(a, 5); // {1, 2, 3, 0, 0}
Java配列は固定長なので、増やしたい場合は「新しい配列を作る」のが基本です。頻繁に増減するなら ArrayList の方が適材適所になります。
java.util.List<Integer> list = new java.util.ArrayList<>();
list.add(1); list.add(2); list.add(3);
System.out.println(list.size()); // 可変長
Javaよくある落とし穴と対策
オフバイワンによる例外
int[] a = {10, 20, 30};
// a[3] = 0; // ArrayIndexOutOfBoundsException(有効な添字は 0〜2)
Java「未満(i < a.length)」を徹底し、書いたら「空・先頭・末尾」の3ケースで必ずテストすると境界バグが激減します。
length と size の取り違え
配列は length(フィールド)、List は size()(メソッド)です。コレクションと配列で API が違うことを覚えておくと、型変換時の混乱を防げます。
参照型配列の初期値が null
String[] s = new String[2]; // {null, null}
if (s[0] == null) s[0] = "sato"; // null を扱ってから使う
Java参照型の配列は「生成直後は null が入る」ことに注意し、使う前に有効値で埋めるか、必ず null チェックを入れます。
例題で身につける
例 1: 区切り文字を最後だけ出さない
public class PrintWithComma {
public static void main(String[] args) {
int[] a = {10, 20, 30, 40};
for (int i = 0; i < a.length; i++) {
boolean last = (i == a.length - 1);
System.out.print(a[i]);
if (!last) System.out.print(", ");
}
}
}
Java例 2: 長さに応じた中央要素の取得
public class Middle {
public static void main(String[] args) {
int[] a = {10, 20, 30, 40, 50};
int mid = a[a.length / 2]; // 偶数長は右寄り
System.out.println(mid); // 30
}
}
Java例 3: 安全なコピーと拡張
import java.util.Arrays;
public class Extend {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = Arrays.copyOf(a, a.length + 2);
System.out.println(Arrays.toString(b)); // [1, 2, 3, 0, 0]
}
}
Java仕上げのアドバイス(重要部分のまとめ)
配列の長さは length(フィールド)で取得し、配列は固定長であることを前提に設計します。走査は「未満」で境界を守り、最後は length - 1 を使うのが安全です。多次元では各行の length を参照して範囲外を避け、参照型配列の初期値 null には必ず備えます。長さ変更は新規配列+コピー、頻繁な増減は ArrayList を選択。配列とコレクションの API(length と size())の違いを意識して、バグの芽を摘みましょう。
