短絡評価を理解する
&&と||は、左の条件だけで結果が決まれば右を実行しません。nullや添字を先に確認する安全な条件式を組み立て、&や|に置き換えると何が変わるかを追います。
この単元で学ぶこと
- &&と||の右辺が実行される条件を説明する
- null・ゼロ除算・配列境界を守る評価順を選ぶ
- 短絡しない演算子や優先順位との違いを追う
本文解説
二つの条件を組み合わせる boolean a=true,b=false;のa&&bは両方trueでないのでfalse、a||bは少なくとも一方trueなのでtrueです。&&と||はbooleanまたはBooleanを使い、整数の0や1を真偽値として暗黙変換しません。まず各条件を比較式などでtrue/falseにします。
ANDはfalseで止まる int n=0;boolean ok=false&&(++n>0);では左がfalseなので右を評価せずnは0です。ANDの結果は右がどうであってもfalseに確定するからです。左がtrueなら右を評価してその結果を採用します。実行の有無と最終のtrue/falseを別々に記録します。
ORはtrueで止まる int n=0;boolean ok=true||(++n>0);では右を実行せずnは0、okはtrueです。左がfalseなら右の結果を調べる必要があります。&&と同じ条件で止まるわけではなく、どの値なら結果が確定するかを演算ごとに考えます。
nullの検査を先に置く String s=null;boolean ok=s!=null&&s.length()>0;はfalseとなり例外を避けます。s.length()>0&&s!=nullでは最初の長さ取得で失敗します。条件の意味が似ていても、左から評価される順序は変えてよいとは限りません。
短絡しない論理演算 boolean同士の&と|は、左が通常完了すれば右も評価します。false&(++n>0)は全体falseでもnを増やします。&は整数ではビット演算にも使えますが、&&は整数のビット演算には使えません。記号一つの差で値だけでなく副作用も変わります。
整数の割り算を守る int d=0;boolean ok=d!=0&&10/d>1;はfalseでゼロ除算を実行しません。d!=0&10/d>1では右も評価されArithmeticExceptionです。ここで扱う整数除算と、浮動小数点のゼロ除算で無限大等になる規則は別です。
配列の境界を確かめる int[] a={4,6};int i=2;boolean ok=i>=0&&i<a.length&&a[i]>0;では二つ目の条件がfalseなのでa[2]を読みません。上限だけでなく下限も必要です。a自体がnullの可能性がある場合は、さらにa!=nullを先頭に置きます。
型検査と実行を分ける false&&missing>0でも、未宣言のmissingはコンパイル時にエラーです。短絡するから文法や型の誤りまで許されるわけではありません。また&&は||より強く結合するためa||b&&cはa||(b&&c)です。括弧で意図を明示し、Booleanのnullが評価される場合は取り出し時の例外も追います。
図解
重要ポイント
- &&は左がfalseなら右を評価しない。
- ||は左がtrueなら右を評価しない。
- booleanの&と|は通常左右を評価する。
- 実行されない式も型検査は必要。
間違えやすい点
- ガードの順序を逆にすると危険な式が先に実行される。
- 右辺の増分や代入が常に起きると思わない。
- Booleanがnullなら評価された時点の取り出しで例外となる。
用語解説
- 短絡評価
- 結果が確定すると後続のオペランドを評価しないこと。
- ガード条件
- 危険な処理を行う前に必要条件を確認する式。
- 副作用
- 式の評価が変数への代入等、周囲の状態を変えること。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
- https://www.oracle.com/jp/education/certification/javase-17-programmer-1/
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-14.html#jls-14.4
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-5.html#jls-5.1.8
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.23
- https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.25
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Objects.html
- https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ArrayList.html
確認問題の出題・採点や学習履歴の保存にはログインが必要です。