Из спецификации языка Java ,
The conditional-or operator || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.
Итак, это проще, чем вы думаете. res = a++ == 2 || --a == 2 && --a == 2;
оценивается так:
res = ((a++ == 2) || ((--a == 2) && (--a == 2)));
a++ == 2
? Постинкремент означает, что a читается как 2 . Затем это выражение оценивается. 2 == 2
, что правда. Короткое замыкание означает, что остальная часть выражения никогда не оценивается.
Итак, по сути, весь приведенный выше код - это res = a++ == 2;
Я сделал простую программу для проверки этого:
public class TestSOCode {
public static void main(String [] args) {
test1();
}
private static void test1(){
int a = 2;
boolean res = false;
//res = a++ == 2 || --a == 2 && --a == 2;
res = expression(a++, "One") || expression(--a, "Two") && expression(--a, "Three");
System.out.println(res +" "+ a);
}
private static boolean expression(int i, String s){
System.out.println(s+ " called with "+ i);
return i == 2;
}
}
Это дает результат
One called with 2
true 3
ОБНОВЛЕНИЕ: После некоторого обсуждения и исследования, я думаю, что было неправильное понимание разницы между приоритетом и порядком выполнения, когда речь идет о логических операторах.
res = a++ == 2 || --a == 2 && --a == 2;
Приоритет вышеприведенного оператора отрабатывается до его оценки. Я не буду переходить к другим правилам предшествования, так как это усложнит этот ответ, поэтому я упросту его:
res = x || y && z;
&&
имеет приоритет, поэтому выражения сгруппированы так:
res = x || (y && z);
Как мы видим, &&
имеет приоритет, поэтому выражения слева и справа сгруппированы вместе, затем ||
вычисляется. Выражение слева от него - x
, а выражение справа - (y && z)
(я думаю, мы оба думали, что если бы приоритет был &&
, это было бы похоже на (a || b) && c
, поэтому сначала он будет оцениваться, но это не так, как это работает). Если мы хотим убедиться, что это действительно так, мы можем изменить приведенный выше код следующим образом:
res = expression(a = 8, "One") || expression(a = 16, "Two") && expression(a = 32, "Three");
Это эквивалентно false || (false && false)
, но без какого-либо вмешательства компилятора в константы времени компиляции. Результат этого:
One called with 8
Two called with 16
false 16
Сначала оценивается ||
, затем левая сторона &&
. Это возвращает false, и false && ?
всегда будет false, поэтому третье выражение не оценивается. Но никакие правила предшествования не были нарушены. Я надеюсь, что это прояснило любую путаницу. Если нет, я с удовольствием продолжу обсуждение в чате и обновлю свой ответ. Поскольку из исходного кода мы знаем, что если первое выражение истинно, ||
возвращает истину и короткие замыкания, мы можем сказать, что a || b && c
не сгруппированы в (a || b) && c
.