09_オブジェクトの配列試験範囲

対象:クラスとインスタンスを学んだ後 / オブジェクトを並べた配列の扱いを理解します


■ 1. 基本型の配列と何が違うのか

これまで 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(参照型の初期値)になっています。
オブジェクトを使うには各要素にオブジェクトを別途代入する必要があります。

■ 2. オブジェクト配列のメモリイメージ

オブジェクト配列の各要素は「オブジェクトの実体」ではなく「オブジェクトを指す参照(アドレス)」を持ちます。これがオブジェクト配列の最大の特徴です。

ステップ① String[] names = new String[3]; null [0] null [1] null [2] ← 全要素 null(実体なし) ステップ② names[0] = "Taro"; names[1] = "Hana"; 0x1a [0] 0x2b [1] null [2] "Taro" (0x1a) "Hana" (0x2b) 配列の要素は 「アドレスのコピー」を持ち 別の場所の実体を指す ← [0],[1] にアドレスが入った
new String[3] は3つの「アドレス置き場」を作るだけ。実体は別途代入する必要があります。

■ 3. オブジェクト配列の典型パターン

● パターン1:宣言と同時に初期値リテラルで作る(短い)

// 一度に作る
String[] names = {"Taro", "Hana", "Jun"};

System.out.println(names[0]);  // → Taro
System.out.println(names.length); // → 3

● パターン2:空の配列を作って後から代入(自由度が高い)

// ① まず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 + ")");
        }
    }
}
Taro (20) Hana (22) Jun (19)

■ 4. null のまま使うと NullPointerException

オブジェクト配列の要素を代入せずに使うと、実行時エラーになります。

String[] names = new String[3];
// names[0] には何も代入していない(null のまま)

System.out.println(names[0].length());  // 実行時エラー!
// → java.lang.NullPointerException
これは NullPointerException(通称 NPE、ヌルポ)と呼ばれる代表的なエラー。
「null(実体なし)に対してメソッドを呼ぼうとした」というエラーです。Java を学ぶ過程で最も多く出会うエラーのひとつ。
なぜ ArrayIndexOutOfBoundsException ではないのか?

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 + " 円");
    }
}
初期状態 books[0]: null Java入門 : 2500 円 C言語 : 1800 円 Python : 3200 円 合計: 7500 円

● 動いたら変えてみましょう

#変えてみること確認ポイント
1② の books[0] = new Book(...) を1行だけ削除する拡張for文で books[0] が null になり、b.title で NullPointerException が出ることを確認しましょう
2配列リテラルで一気に作る:Book[] books = { new Book(...), new Book(...), new Book(...) };パターン1の書き方で同じ結果になることを確認しましょう
3books[3] = new Book(...) を追加する配列のサイズは 3 なので、ArrayIndexOutOfBoundsException が発生することを確認しましょう(NullPointerException との違いを比較)

試験との対応

よく問われること正しい答え
オブジェクト配列を new クラス[N] で作ったとき各要素の初期値null
null のまま .メソッド() を呼ぶNullPointerException
オブジェクト配列の .length要素数を返す(基本型配列と同じ)
オブジェクトの代入方法各要素に new クラス(...) で生成して代入する

■ 理解度チェック問題

問題09-1

次のJavaコードの出力として正しいものはどれか。

String[] names = new String[3];
System.out.println(names[0]);
解説を表示 正解:ウ
オブジェクト(参照型)配列を new で作ったとき、各要素はnullに初期化される。基本型配列(int は 0、boolean は false)と違うので注意。println(null) は文字列 "null" として表示される。

問題09-2

Person クラスのオブジェクトを配列の最初の要素に代入する正しい書き方はどれか。

Person[] people = new Person[3];
people[0] = ____;
解説を表示 正解:ア
Javaのオブジェクト生成は必ず new クラス名(引数) の形。new を省略するとコンパイルエラー。create() のような静的ファクトリは Java の標準仕様ではない(必要なら自分で書くもの)。

問題09-3

次のJavaコードの出力として正しいものはどれか。

Person[] people = new Person[5];
System.out.println(people.length);
解説を表示 正解:イ
.length は配列のサイズを返す。要素が null かどうかは関係なく、new Person[5] なら 5。基本型配列と同じ仕様。

問題09-4

次のJavaコードを実行した結果として正しいものはどれか。

String[] names = new String[3];
System.out.println(names[0].length());
解説を表示 正解:エ
names[0]null。null に対して .length() を呼ぼうとすると NullPointerException(NPE)が発生する。配列の範囲内アクセスなので ArrayIndexOutOfBoundsException ではない点に注意。

問題09-5

次の「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)