変数の宣言と初期化のコードトレース
変数の宣言は名前と型を決め、初期化は最初の値を与える操作です。ローカル変数には自動の初期値がないことを押さえ、代入・再代入・確定代入をコードの経路で判断します。
この単元で学ぶこと
- 宣言・初期化・再代入を区別する
- ローカル変数の確定代入を判定する
- 型とスコープに沿って値の変化を追う
本文解説
分岐を合流地点まで追う int n;if(args.length==0){n=10;}else{n=20;}の直後ならnを読めます。片方だけで代入する場合と両方で代入する場合を、合流地点で比較します。条件の値がわからなくても全経路の代入が証明できれば成立します。
終了する経路 int n;if(args.length==0){return;}else{n=20;}の後はnを読めます。returnした経路は後の読取りへ到達しないためです。確定代入はすべての分岐に代入文があるかだけでなく、読取りに到達する経路を調べます。
ブロックとスコープ {int n=2;}の閉じ波括弧の外ではnを使えません。一方{int n=2;}{int n=3;}は互いに重ならないブロックなので同名を使えます。外側で生存するローカル変数と同名を内側で宣言することはできません。
finalの初回代入 final int n;n=3;は宣言後の一度の代入として合法です。その後n=4;は拒否されます。finalは常に宣言行で初期化するという意味ではなく、変数へ二度代入できないという制約です。経路ごとに初回代入となるif/elseも可能です。
final参照の意味 final int[] a={1};a[0]=2;は可能です。finalが固定するのはaに入る参照であり、配列の要素ではありません。a=new int[]{2};は参照の再代入なので拒否されます。変更禁止の対象を変数と実体に分けます。
初期化子の評価順 int a=2,b=++a,c=a+b;ではaが3になり、その3をbへ入れ、cは6になります。複数宣言は左から順に評価します。ただしint a=b,b=2;ではbがまだスコープに入っていないためエラーです。後の宣言を遡って参照できません。
ループの代入 int n;do{n=7;}while(false);の後は一度本体を通るためnを読めます。while(args.length>0){n=7;}では一度も本体を通らない可能性があり、後でnを読めません。見た目の代入文の有無でなく実行経路を確認します。
自己更新と型 int n=2;n+=3;はnを5に更新します。代入式そのものも値を持つためint a=1,b=2;System.out.print(a=b);は2を表示しaも2です。比較したい場合はa==bと書きます。boolean変数の代入も合法なので、ifへの代入混入には特に注意します。
図解
重要ポイント
- ローカル変数は読む前に値を代入する。
- 代入は右辺の値を左辺の変数へ格納する。
- 同じブロックで同名のローカル変数を重複宣言できない。
- final変数には代入回数の制約がある。
間違えやすい点
- 宣言だけで0が入ると考えない。
- 変数のコピー後の再代入を別変数へ波及させない。
- 代入の=と比較の==を区別する。
用語解説
- 宣言
- 変数の名前と型を導入する記述。
- 初期化
- 変数へ最初の値を与えること。
- 確定代入
- 変数を読む場所へ到達する全経路で代入済みと証明できる状態。
- スコープ
- その名前で変数を参照できるソースコードの範囲。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。