フィールドとローカル変数のコードトレース
フィールドはクラスやインスタンスの状態を保持し、ローカル変数はメソッド等の処理の中で使います。宣言位置、初期値、スコープ、同名変数が現れた場合の名前解決を分けて学びます。
この単元で学ぶこと
- フィールドとローカル変数の宣言位置を区別する
- 既定値と確定代入を判断する
- 同名変数による隠蔽とthisを追う
本文解説
フィールド初期化の順 class Box{int a=2;int b=a+3;}ではaを2へ初期化してbを5にします。インスタンスフィールド初期化子はソース上の順に実行されます。後のフィールドを単純名で先読みする記述には前方参照の制約があるため、依存する値は先に定義します。
初期化の副作用 int a=2;int b=++a;ならaもbも3になります。フィールド初期化でも通常の式の評価順が適用されます。二つの実体をnewした場合は、それぞれのフィールド初期化が行われます。
ローカル更新と状態更新 int n=2;void run(){int n=5;n++;}ではフィールドは2です。this.n++を実行した場合だけフィールドが増えます。ローカル変数とフィールドの同名が合法である点は、入れ子ブロックのローカル同士の重複宣言が不正な点と違います。
引数値の変更 void set(int n){n++;this.n=n;}に4を渡すとフィールドは5ですが呼出し側のint変数は4のままです。仮引数はローカルな変数です。値渡しとthisによる状態書換えを同じ行に混ぜず、それぞれの格納場所で追います。
引数の名前とフィールド void set(int value){n=value;}なら名前が違うのでthisなしでもフィールドnを参照できます。thisを常に書かなければフィールドへ代入できないわけではありません。名前が重なる場合に明示する役割を理解します。
ローカル変数の有効範囲 if内のint xはそのブロック外で使えません。別々のブロックで同名を再利用することは可能です。メソッドの引数名と同じローカル変数をメソッド本体へ重複宣言することはできません。
フィールドのfinal final int n=3は後から代入できません。初期化子のないfinalインスタンスフィールドは、各コンストラクタの正常終了までに必ず一度代入する必要があります。通常のintフィールドの既定値0があるから未代入のままでよい、とはなりません。
カプセル化と検査 private int n;public void set(int x){if(x>=0)n=x;}なら負値を無視して状態を保つ設計です。外側から直接nへ代入できないことでこの入口を通せます。privateだけで自動検査されるわけではなく、更新メソッドに必要な検査を書くことが重要です。
図解
重要ポイント
- フィールドはクラス本体、ローカル変数はメソッド等のブロックで宣言する。
- フィールドには型に応じた既定値がある。
- ローカル変数には読取り前の確定代入が必要。
- 同名のローカル変数があれば単純名はそちらを表す。
間違えやすい点
- フィールドの既定値をローカル変数へ適用しない。
- 同じ名前なら常に同じ格納場所と思わない。
- privateフィールドを別トップレベルクラスから直接読まない。
用語解説
- フィールド
- クラス本体で宣言する状態用の変数。
- ローカル変数
- メソッド等のブロック内で宣言する変数。
- 隠蔽
- 同名の近いスコープの宣言により単純名の参照先が変わること。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。