対象:C言語経験者 / 宣言・生成の構文差分と、Javaならではの安全機能を理解します
| 項目 | C言語 | Java |
|---|---|---|
| 宣言の書き方 | int a[5]; | int[] a = new int[5]; |
[] の位置 | 変数名の後ろ | 型の後ろ(推奨) |
| 要素数の取得 | 自分で管理(マクロなど) | a.length で取得できます |
| 初期値 | 不定(ゴミ値) | 自動で 0 / false / null に初期化されます |
| 範囲外アクセス | メモリ破壊(未定義動作) | ArrayIndexOutOfBoundsException(実行時エラー) |
| 配列は参照型 | ポインタで扱う | 参照型として扱います(null 代入可) |
| 多次元配列 | int a[3][4]; | int[][] a = new int[3][4]; |
Javaの配列は new キーワードで生成します。new を使うと JVM がメモリを確保してくれます。C言語の malloc に相当しますが、free は不要(GCが自動解放)です。
int a[5]; // スタック上に確保 int *b = malloc(5 * sizeof(int)); // 使い終わったら free(b) が必要
int[] a = new int[5]; // ヒープ上に確保 // free 不要(GCが自動解放)
// パターン1:宣言と生成を別々に
int[] a;
a = new int[5];
// パターン2:宣言と同時に生成
int[] a = new int[5];
// パターン3:初期値を指定(要素数は自動で決まる)
int[] a = {10, 20, 30, 40, 50};
// パターン4:new と初期値を同時に(パターン3と同じ意味)
int[] a = new int[]{10, 20, 30, 40, 50};
[] はJavaでは型の後ろに書くのが推奨です。int[] a と int a[] は両方書けますが、Javaの慣習は int[] です。
配列は参照型です。変数は配列本体を直接持つのではなく、配列が置かれている場所を参照します。
0 に初期化されています。
int[] a = new int[5];
System.out.println(a.length); // → 5
int[] b = {10, 20, 30};
System.out.println(b.length); // → 3
.length でいつでも取得できます。i < a.length と書けば、配列のサイズが変わっても修正不要になります。
C言語では範囲外を読み書きしてもエラーにならずにメモリを壊しました。Javaは範囲外アクセスを実行時に検出して例外を投げます。
int[] a = new int[3]; // インデックス 0, 1, 2 が有効
a[0] = 10; // OK
a[2] = 30; // OK
a[3] = 40; // 実行時エラー:ArrayIndexOutOfBoundsException
// 「配列インデックスが範囲外」という意味
エラーを実際に確認しましょう
07_Array フォルダに ArrayError.java を作って実行しましょう。
public class ArrayError {
public static void main(String[] args) {
int[] a = new int[3];
a[0] = 10;
a[3] = 40; // ← 範囲外
System.out.println(a[0]);
}
}
ターミナルに次のようなエラーが表示されます:
「Index 3 out of bounds for length 3」→「長さ3の配列にインデックス3でアクセスしようとした」という意味です。
エラーメッセージに ファイル名と行番号 が表示されるので、どこが原因かすぐわかります。
確認したら a[3] を a[2] に直して正常動作も確認しましょう。
int a[3][4];
// 初期値あり
int b[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
int[][] a = new int[3][4];
// 初期値あり
int[][] b = {
{1, 2, 3},
{4, 5, 6}
};
int[][] b = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(b.length); // → 2(行数)
System.out.println(b[0].length); // → 3(0行目の列数)
System.out.println(b[1][2]); // → 6(1行目 2列目)
b.length は行数(2)、b[0].length は0行目の列数(3)を返します。
実習1
07_Array フォルダに Array1D.java を作って実行しましょう。
public class Array1D {
public static void main(String[] args) {
// ① 生成と初期値の確認
int[] a = new int[5];
System.out.println("初期値: a[0]=" + a[0] + ", a[4]=" + a[4]);
// ② 値の代入
for (int i = 0; i < a.length; i++) {
a[i] = (i + 1) * 10; // 10, 20, 30, 40, 50
}
// ③ 拡張for文で全要素を出力
System.out.print("要素: ");
for (int x : a) {
System.out.print(x + " ");
}
System.out.println();
// ④ 最大値を探す
int max = a[0];
for (int x : a) {
if (x > max) {
max = x;
}
}
System.out.println("最大値: " + max);
// ⑤ 初期値リテラルで作成
int[] b = {3, 1, 4, 1, 5, 9, 2, 6};
System.out.println("b.length = " + b.length);
}
}
実行結果:
| # | 変えてみること | 確認ポイント |
|---|---|---|
| 1 | ④ の最大値を探すコードを最小値を探すコードに書き換える | max → min、> → < に変えるだけで動きます |
| 2 | int[] a = new int[5] を boolean[] flags = new boolean[3] に変えて初期値を確認する |
boolean の初期値は false、String の初期値は null になります |
| 3 | ⑤ の配列 b を拡張for文で合計と平均を求めるコードを追加してみる |
実習2(LoopAdvanced)でやった内容の応用です。自分で書けるか試しましょう |
実習2
08_Array2D フォルダに Array2D.java を作って実行しましょう。
public class Array2D {
public static void main(String[] args) {
// ① 2次元配列の生成と代入
int[][] table = new int[3][4];
for (int row = 0; row < table.length; row++) {
for (int col = 0; col < table[row].length; col++) {
table[row][col] = row * 10 + col;
}
}
// ② 表形式で出力
System.out.println("--- table ---");
for (int row = 0; row < table.length; row++) {
for (int col = 0; col < table[row].length; col++) {
System.out.printf("%4d", table[row][col]);
}
System.out.println();
}
// ③ 初期値リテラルで2次元配列
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// ④ 行数と列数
System.out.println("\nmatrix: " + matrix.length + "行 "
+ matrix[0].length + "列");
// ⑤ 対角成分を出力(行と列のインデックスが同じ要素)
System.out.print("対角: ");
for (int i = 0; i < matrix.length; i++) {
System.out.print(matrix[i][i] + " ");
}
System.out.println();
}
}
実行結果:
| # | 変えてみること | 確認ポイント |
|---|---|---|
| 1 | ② の出力ループを拡張for文に書き換えてみる | for (int[] row : table) → for (int val : row) の2重拡張for文で書けます。インデックスが不要なことを確認しましょう |
| 2 | ③ の matrix の全要素の合計を求めるコードを追加する |
2重ループで全要素を足し合わせましょう。答えは 1+2+…+9 = 45 になります |
| 3 | matrix[3][0] にアクセスしてみる(行数は3なので存在しない) |
ArrayIndexOutOfBoundsException が発生することを確認しましょう |
頻出ポイント
| よく問われること | 正しい答え |
|---|---|
| 配列の初期値 | int は 0、boolean は false、参照型は null |
| 要素数の取得 | 配列名.length(メソッドではなくフィールド。() 不要) |
| 範囲外アクセス | コンパイルエラーではなく ArrayIndexOutOfBoundsException(実行時エラー) |
| 2次元配列の行数 | a.length |
| 2次元配列の列数 | a[0].length |
.length は フィールド(変数)なので () は不要です。a.length() と書くとコンパイルエラーになります。String の .length() はメソッドなので () が必要。混同しやすいので注意しましょう。
public class Q {
public static void main(String[] args) {
int[] data = {3, 5, 6, 9, 10, 13, 16};
for (int i = 0; i < data.length; i += 2) {
System.out.print(data[i] + ", ");
}
}
}
i が 0, 2, 4, 6 と 2 ずつ増えます。data[0]=3, data[2]=6, data[4]=10, data[6]=16 が出力されます。
public class Q2 {
public static void main(String[] args) {
String[] names = new String[3];
System.out.println(names[0]);
System.out.println(names.length);
}
}
参照型(String)の配列は、生成直後の要素が null に初期化されます。length は要素数の 3 を返します。
| ポイント | 内容 |
|---|---|
| 宣言 | int[] a = new int[5];。[] は型の後ろに書くのが慣習 |
| 初期値 | 自動初期化。int は 0、boolean は false、参照型は null |
.length | 要素数を取得。() 不要(フィールド) |
| 範囲外アクセス | ArrayIndexOutOfBoundsException。C言語のような無音のメモリ破壊は起きません |
| 2次元配列 | int[][] a = new int[行][列];。行数は a.length、列数は a[0].length |
| new | 配列はヒープに確保。free 不要(GC が解放) |