クラスとインスタンスのコードトレース

クラスはオブジェクトの型と振舞いを定義し、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を二回行えば二つの実体を作る。

重要ポイント

  • クラス名は型として使い、newは実体を生成する。
  • インスタンスフィールドは実体ごとに別の値を持つ。
  • 変数への参照代入は実体の複製ではない。
  • nullのインスタンスメンバーへアクセスすると例外。

間違えやすい点

  • 参照変数を宣言しただけで実体ができると思わない。
  • 二つのnewと二つの参照変数を同一視しない。
  • インスタンスのフィールドをクラス名だけで参照しない。

用語解説

クラス
フィールドやメソッド等を定義する型。
インスタンス
クラスを基に生成した具体的なオブジェクト。
インスタンスフィールド
各実体が個別に持つ状態を表す変数。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。