2020/04/30

Java のショートサーキット演算子の評価順序

ショートサーキット演算子 (&&, ||) の結合優先順位は && が先で || が後です。
でも、評価順序はどうなっているのでしょう? a || b && c という式で試してみました。

検証プログラム

class ConditionalOperatorPrecedence {
  public static void main(String[] args) {
    for (int i = 0; i < 8; i++) {
      boolean a = (i & 1) != 0;
      boolean b = (i & 2) != 0;
      boolean c = (i & 4) != 0;
      System.out.println(
          a + " || " + b + " && " + c + " -> " + (expression("a", a) || expression("b", b) && expression("c", c)));
      System.out.println();
    }
  }

  public static boolean expression(String msg, boolean value) {
    System.out.println(msg);
    return value;
  }
}

a || b && c の各 a, b, c について true, false を網羅的にあてはめて、全8パターンを実行します。
expression() は評価されたときに msg を出力するために用意したメソッドです。expression("a", a) とすると、評価されたときに "a" を表示して、a の値を返します。a, b, c がどの順番に表示されるかで、評価順序が分かります。

結果

a
b
false || false && false = false

a
true || false && false = true

a
b
c
false || true && false = false

a
true || true && false = true

a
b
false || false && true = false

a
true || false && true = true

a
b
c
false || true && true = true

a
true || true && true = true


最初のケース false || false && false を見てみると、a, b の順に評価されて、c が評価されていないことが分かります。また、結合優先順位が高いからといって、先に評価されるわけではないことも分かります。評価は左から順に行われています。

  • a を評価
  • a が false なので、|| は評価終了せず、右オペランドへ
  • b を評価
  • b が false なので、&& の評価は終了
  • false || false が評価され、結果 false
7番目の例 false || true && true を見ると、a, b, c 全て評価されています。&& を先に評価していれば、? || true == true が確定して a を評価する必要はありませんが、そんなことにはなりません。

言われてみれば当然なのですが、結合優先順位と評価順序を取り違えてしまうことがあるので気を付けてください。