対象:クラスとインスタンスを学んだ後 / オブジェクトを並べた配列の扱いを理解します
これまで int[] や double[] などの基本型の配列を学びました。配列の要素には String や自分で作ったクラスのインスタンス(オブジェクト)を入れることもできます。これをオブジェクトの配列と呼びます。
int[] nums = new int[3]; // 要素は 0 で初期化されている System.out.println(nums[0]); // → 0 nums[0] = 10;
String[] names = new String[3]; // 要素は null で初期化されている System.out.println(names[0]); // → null names[0] = "Taro";
null(参照型の初期値)になっています。オブジェクト配列の各要素は「オブジェクトの実体」ではなく「オブジェクトを指す参照(アドレス)」を持ちます。これがオブジェクト配列の最大の特徴です。
new String[3] は3つの「アドレス置き場」を作るだけ。実体は別途代入する必要があります。
// 一度に作る
String[] names = {"Taro", "Hana", "Jun"};
System.out.println(names[0]); // → Taro
System.out.println(names.length); // → 3
// ① まず3つ分の「アドレス置き場」を作る String[] names = new String[3]; // ② 各要素にオブジェクトを代入 names[0] = "Taro"; names[1] = "Hana"; names[2] = "Jun"; // 代入しないと null のまま String[] empty = new String[3]; System.out.println(empty[0]); // → null
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
// ① 配列だけ作成(全要素 null)
Person[] people = new Person[3];
// ② 各要素に new で生成して代入
people[0] = new Person("Taro", 20);
people[1] = new Person("Hana", 22);
people[2] = new Person("Jun", 19);
// ③ 拡張for文でアクセス
for (Person p : people) {
System.out.println(p.name + " (" + p.age + ")");
}
}
}
オブジェクト配列の要素を代入せずに使うと、実行時エラーになります。
String[] names = new String[3]; // names[0] には何も代入していない(null のまま) System.out.println(names[0].length()); // 実行時エラー! // → java.lang.NullPointerException
names[0] へのアクセス自体は配列の範囲内なので、配列の範囲外エラーは出ません。
出るのは「取り出した要素が null だったため、その null に対して .length() メソッドを呼ぼうとした」という別のエラーです。
2つのエラーは別物。エラーメッセージを読んで原因を切り分けましょう。
実習
09_ObjArray フォルダに BookList.java を作って実行しましょう。
class Book {
String title;
int price;
Book(String title, int price) {
this.title = title;
this.price = price;
}
}
public class BookList {
public static void main(String[] args) {
// ① 配列だけ作成(要素は null)
Book[] books = new Book[3];
System.out.println("初期状態 books[0]: " + books[0]);
// ② 各要素にオブジェクトを代入
books[0] = new Book("Java入門", 2500);
books[1] = new Book("C言語", 1800);
books[2] = new Book("Python", 3200);
// ③ 拡張for文で表示と合計
int total = 0;
for (Book b : books) {
System.out.println(b.title + " : " + b.price + " 円");
total += b.price;
}
System.out.println("合計: " + total + " 円");
}
}
| # | 変えてみること | 確認ポイント |
|---|---|---|
| 1 | ② の books[0] = new Book(...) を1行だけ削除する | 拡張for文で books[0] が null になり、b.title で NullPointerException が出ることを確認しましょう |
| 2 | 配列リテラルで一気に作る:Book[] books = { new Book(...), new Book(...), new Book(...) }; | パターン1の書き方で同じ結果になることを確認しましょう |
| 3 | books[3] = new Book(...) を追加する | 配列のサイズは 3 なので、ArrayIndexOutOfBoundsException が発生することを確認しましょう(NullPointerException との違いを比較) |
試験との対応
| よく問われること | 正しい答え |
|---|---|
オブジェクト配列を new クラス[N] で作ったとき各要素の初期値 | null |
null のまま .メソッド() を呼ぶ | NullPointerException |
オブジェクト配列の .length | 要素数を返す(基本型配列と同じ) |
| オブジェクトの代入方法 | 各要素に new クラス(...) で生成して代入する |
次のJavaコードの出力として正しいものはどれか。
String[] names = new String[3]; System.out.println(names[0]);
new で作ったとき、各要素はnullに初期化される。基本型配列(int は 0、boolean は false)と違うので注意。println(null) は文字列 "null" として表示される。
Person クラスのオブジェクトを配列の最初の要素に代入する正しい書き方はどれか。
Person[] people = new Person[3]; people[0] = ____;
new クラス名(引数) の形。new を省略するとコンパイルエラー。create() のような静的ファクトリは Java の標準仕様ではない(必要なら自分で書くもの)。
次のJavaコードの出力として正しいものはどれか。
Person[] people = new Person[5]; System.out.println(people.length);
.length は配列のサイズを返す。要素が null かどうかは関係なく、new Person[5] なら 5。基本型配列と同じ仕様。
次のJavaコードを実行した結果として正しいものはどれか。
String[] names = new String[3]; System.out.println(names[0].length());
names[0] は null。null に対して .length() を呼ぼうとすると NullPointerException(NPE)が発生する。配列の範囲内アクセスなので ArrayIndexOutOfBoundsException ではない点に注意。
次の「new Person[3] で作った配列の全要素にオブジェクトを設定する」方法として正しいものはどれか。
new Person[3] は「3つ分のアドレス置き場」を作るだけで、Person オブジェクト自体は生成されない。各要素にオブジェクトを設定するには、必ず別途 new Person(...) で生成して代入する必要がある。配列リテラル { new Person(...), new Person(...), new Person(...) } なら一度に書ける。
| ポイント | 内容 |
|---|---|
| 初期値 | オブジェクト配列の各要素は null(基本型配列とは違う) |
| 要素への代入 | 各要素に new でオブジェクトを生成して代入する必要があります |
| 配列リテラル | { new Person(...), new Person(...) } で一度に作れます |
.length | 配列のサイズ。null かどうかは関係なし |
| null のまま使うと | NullPointerException(NPE) |