004-006-008
配列変数の参照を理解する
初級
問題説明
配列参照の代入:共有状態の理解
Javaの配列は値型ではなく参照型です。この基本概念が、配列を別の変数に代入すると独立したコピーではなく共有状態が作られる理由を説明しています。
参照の概念は最初は難しく感じるかもしれませんが、一緒に理解していきましょう。
学習目標
- 配列変数への参照代入の動作を実装で確認できる
- 参照代入により同一配列を指す複数変数の関係を適用できる
- 参照型変数と基本型変数の代入の違いを説明できる
学習ポイント
- 参照と値: 配列変数はデータではなくメモリアドレスを保持
- 共有状態: 2つの変数が同じ配列を指すことができる
- 副作用: 一方の変数経由の変更は全参照に影響
- 防御的コピー: 独立性にはclone()やArrays.copyOf()を使用
参照コピーの動作
int[] numbers1 = {10, 20, 30}; int[] numbers2 = numbers1; // 参照のコピー、配列のコピーではない
numbers2[0] = 100;
System.out.println(numbers1[0]); // 100を出力(同じ配列!)
プリミティブ型と参照型
| プリミティブ(int) | 参照(int[]) |
|---|---|
| |
よくある間違い
参照とコピーの違いでつまずいても心配ありません。もう一度コードを見直して、それぞれの動作を確認してみましょう。
間違い1: 独立したコピーを期待
問題のあるコード:
int[] original = {1, 2, 3};
int[] backup = original; // バックアップではない!
original[0] = 999;
// backup[0]も999 - データ「消失」正しいコード:
int[] original = {1, 2, 3};
int[] backup = original.clone(); // 真のコピー
original[0] = 999;
// backup[0]は依然1間違い2: 意図しないメソッドの副作用
問題のあるコード:
void sortArray(int[] arr) {
Arrays.sort(arr); // 呼び出し元の配列を変更!
}防御的なコード:
void sortArray(int[] arr) {
int[] copy = arr.clone();
Arrays.sort(copy); // オリジナルは変更されない
}真のコピーを作成する方法
// 方法1: clone() int[] copy1 = original.clone();// 方法2: Arrays.copyOf()
int[] copy2 = Arrays.copyOf(original, original.length);
// 方法3: System.arraycopy()
int[] copy3 = new int[original.length];
System.arraycopy(original, 0, copy3, 0, original.length);
実務での活用
- 防御的プログラミング: 信頼できないソースからの配列をクローン
- イミュータブルクラス: 内部配列ではなくコピーを返す
- メソッドパラメータ: 配列が変更されるかドキュメント化
補足: オブジェクト配列の場合、clone()は浅いコピーを作成します。配列は新しいですが、要素は依然として参照を共有しています。
前提知識の詳細説明
この問題を解くために必要な知識を確認しましょう。
基本概念
この問題で扱うプログラミングの基本概念を理解することが、正しい解答への第一歩です。コードの各要素がどのように連携して動作するかを把握しましょう。
実装アプローチ
問題を解くための考え方を段階的に整理します:
- 問題文を読み、入力と出力の関係を理解する
- 必要な変数やデータ構造を特定する
- 処理の流れを組み立てる
- テストケースで動作を確認する
