if・elseのコードトレース
割引対象と試験合否の判定を修正します。同じ値でも条件の順番や波括弧が違えば出力が変わります。実行される条件、実行されない副作用、分岐後に残る値まで追跡します。
この単元で学ぶこと
- ifとelseの対応を文の構造から判断できる
- 比較・短絡評価・代入の違いを説明できる
- 境界値と変数の初期化を含むコードを追跡できる
本文解説
条件を表にする 80点以上をA、60点以上80点未満をB、それ未満をCとします。score=80ならAです。if(score>=60)を先に置くと80もそこで選ばれてBとなるため、A条件へ届きません。分類の重なりを考え、厳しい範囲から判定します。
独立条件の上書き String grade="C"; if(score>=80){grade="A";} if(score>=60){grade="B";}では85点でも最後はBです。二つ目も実行されるためです。一つの分類ならelse ifへつなげ、複数の独立した特典なら二つのifを使うなど目的を決めます。
境界の検証 条件score>60なら60は合格しません。必要な条件が60以上なら>=へ直します。59・60・61の結果を期待値と照合し、さらに80のような次の境界も試します。平均的な値一つの成功だけで全区間が正しいとは判断しません。
elseを外側へ移す boolean member=false, coupon=false; if(member){if(coupon){System.out.print("discount");}}else{System.out.print("regular");}ではregularです。波括弧が内側ifを閉じた後のelseなので外側と対応します。元の字下げを信用せず、括弧の組を先にたどります。
短絡とカウンター int count=0; boolean ok=false && ++count>0;ではcountは0です。左をtrueへ変えれば++countが実行され1です。条件の中に更新を書くと評価の省略が状態に影響するため、まず一文ずつ更新と判定を分けると確認しやすくなります。
nullを安全に扱う String name=null; boolean empty=name==null || name.length()==0;はtrueです。左でnullと分かれば右を評価しません。name.length()==0 || name==nullと逆にすると最初に例外になるため、同じ条件語があっても順序は交換できません。
代入経路をそろえる int fee; if(member){fee=80;}else{fee=100;}ならどちらの経路も値を持ちます。一方if(member){int fee=80;}と内側で宣言すると、外側ではそのfeeを参照できません。代入漏れとスコープ外参照は別のコンパイルエラーとして区別します。
再現できる確認 条件を固定した短いmainをケースごとに作り、出力と最後の変数をprintlnで確認します。コンパイルが失敗する例は成功例と別のファイルで試します。失敗理由を「型」「未代入」「スコープ」に分けると、実行結果の予測と混同しません。
図解
重要ポイント
- 条件はbooleanまたはBooleanであり、数値を真偽として扱わない。
- else ifは最初の真の枝、独立したifはそれぞれ評価する。
- 波括弧・空文・elseの対応で実行範囲が決まる。
- 短絡評価では右辺の副作用や例外も省略される。
間違えやすい点
- 字下げで処理範囲を判断しない。
- =と==を混同しない。
- 境界値の等号と、未代入になる経路を確認する。
用語解説
- boolean
- trueまたはfalseを持つ基本型。if条件に使う。
- ブロック
- 波括弧で複数の文をまとめたもの。
- 短絡評価
- 左側の結果だけで決まるとき、右側を評価しない仕組み。
- 空文
- セミコロンだけからなる、処理を行わない文。
- 確実な代入
- ローカル変数が読み出される前に値が代入されることをコンパイラが確認する規則。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。