クラスとインスタンスのコードトレース
クラスはオブジェクトの型と振舞いを定義し、newで作るインスタンスは具体的な状態を持ちます。クラスの宣言、生成、参照、フィールドへのアクセスを区別して、複数の実体の値を追います。
この単元で学ぶこと
- クラス宣言とインスタンス生成を区別する
- 各インスタンスのフィールドの独立性を追う
- 参照の共有とメソッド呼出しを判断する
本文解説
メソッドの受け手を固定する class Counter{int n;void add(int x){n+=x;}}でa.add(2);b.add(3);は別の受け手を更新します。aとbが別newか同じ参照かを最初に図にします。呼出し回数だけを数えても対象を見落とすと正答できません。
引数を渡す int v=4;a.add(v);v=9;としてもaへ加えた値は4です。メソッドへ渡すのは呼出し時点の値です。後から引数に使った変数を変更しても、過去のメソッド呼出しがやり直されるわけではありません。
参照も値渡し void set(Box b){b.value=8;}は引数参照のコピーを通じて共有実体を変えます。void reset(Box b){b=new Box();}は仮引数bを付け替えるだけです。呼出し側の変数そのものを書き換える処理ではありません。
戻り値の参照 Box same(){return this;}の戻り値は呼出し先と同じ実体への参照です。一方Box copy(){return new Box();}なら新実体です。メソッド呼出しを含む参照代入でも、生成しているのか同じ参照を返しているのかを確認します。
配列とクラス実体 Box[] a=new Box[2];の各要素はnullです。a[0]=new Box();として初めて先頭から実体へアクセスできます。配列実体が一つあることとBox実体が二つあることは同じではありません。
オブジェクト配列の共有 Box b=new Box();Box[] a={b,b};では両要素が同じ実体を指します。a[0].value=7とすればa[1].valueも7です。new Box()を二回列挙した配列との違いは、要素数でなく生成回数にあります。
同じ値でも同じ実体ではない 二つのBoxへ同じvalueを入れても==はfalseです。Objectから継承したequalsを独自実装していないBoxではequalsも参照同一性です。Stringのequalsが内容比較をするからといって、すべての自作クラスが自動で全フィールドを比較するとは限りません。
nullへメソッドを呼ぶ Box b=null;b.show();はインスタンスメソッドの呼出し前に失敗します。showの本体がフィールドを使わず固定文字列を返すだけでも同じです。インスタンスの受け手が必要という規則が先に適用されます。
図解
重要ポイント
- クラス名は型として使い、newは実体を生成する。
- インスタンスフィールドは実体ごとに別の値を持つ。
- 変数への参照代入は実体の複製ではない。
- nullのインスタンスメンバーへアクセスすると例外。
間違えやすい点
- 参照変数を宣言しただけで実体ができると思わない。
- 二つのnewと二つの参照変数を同一視しない。
- インスタンスのフィールドをクラス名だけで参照しない。
用語解説
- クラス
- フィールドやメソッド等を定義する型。
- インスタンス
- クラスを基に生成した具体的なオブジェクト。
- インスタンスフィールド
- 各実体が個別に持つ状態を表す変数。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。