Вот сегменты кода
. Можете ли вы объяснить, почему выходы различаются?
1) Выход
public static ShortCkt {
public static void main(String args[]) {
int i = 0;
boolean t = true;
boolean f = false, b;
b = (t && ((i++) == 0));
b = (f && ((i+=2) > 0));
System.out.println(i);
}
}
в этом случае равен 1
2) Выход
public static ShortCkt {
public static void main(String args[]) {
int i = 0;
boolean t = true;
boolean f = false, b;
b = (t & ((i++) == 0));
b = (f & ((i+=2) > 0));
System.out.println(i);
}
}
в этом случае равен 3
3 ) Выход
public static ShortCkt {
public static void main(String args[]) {
int i = 0;
boolean t = true;
boolean f = false, b;
b = (t || ((i++) == 0));
b = (f || ((i+=2) > 0));
System.out.println(i);
}
}
в этом случае равен 2
4) Выход
public static ShortCkt {
public static void main(String args[]) {
int i = 0;
boolean t = true;
boolean f = false, b;
b = (t | ((i++) == 0));
b = (f | ((i+=2) > 0));
System.out.println(i);
}
}
в этом случае равен 3
Почему вывод отличается в случае &&, &, || ?
Так же как в C/C++ &&
оценивается "лениво", а &
- нет.
Если a
ложно, то a && b
вернет false, даже не оценивая b
.
То же самое касается a || b
: Если первый операнд, a
, истинен, то все выражение истинно, а второй операнд, b
, никогда не оценивается. Для a | b
, однако, и a
, и b
будут оценены.
Это имеет последствия, если операнд, который не оценивается при использовании &&
(или ||
), имеет побочные эффекты, как в ваших примерах.
Побочное замечание: немногие java-программисты знают, что ^
(xor) работает и для булевых чисел. (Версии ^^
не существует просто потому, что она была бы избыточной)
Существует 4 булевых
бинарных оператора, которые мы здесь рассматриваем:
&&
- условный и оператор
&
- логический и оператор||
- условный оператор or
|
- логический оператор orВот ключевой момент:
true
только если оба операнда true
false
, результат будет false
независимо от правого операндаtrue
только если хотя бы один операнд будет true
true
, результат будет true
независимо от правого операндаДругими словами, при условии отсутствия исключений и т.д:
&
и |
всегда оценивают оба операнда&&
и ||
оценивают правый операнд условно; правый операнд оценивается только если его значение может повлиять на результат бинарной операции. Это означает, что правый операнд НЕ оценивается, если:
&&
оценивается в false
false
)||
оценивается в true
true
)&
, ^
и |
&
результатом будет true
, если оба операнда равны true
; в противном случае результатом будет false
. |
результатом будет false
, если оба операнда равны false
; в противном случае результатом будет true
. &&
&&
похож на &
, но оценивает свой правый операнд только в том случае, если значение его левого операнда равно true
. ||
||
подобен |
, но оценивает свой правый операнд, только если значение его левого операнда равно false
. &&
и ||
- это логические операторы И и ИЛИ, они всегда приводят к логическому выражению
. &
и |
- побитовые операторы И и ИЛИ, они выполняют побитовое сравнение каждой стороны. Для получения дополнительной информации о том, что делают эти операторы, см. по этой ссылке
Это происходит потому, что && и || являются логическими операторами, которые имеют "механизм короткого замыкания". Если вы используете || и первое выражение оценивается как true, второе не будет оценено и, следовательно, i не будет вычислено. & и | - битовые операторы, которые выполняют битовые вычисления на входе. Они не имеют короткого замыкания, и поэтому все выражение оценивается независимо от того, что происходит.
Операторы &
и |
являются побитовыми, и поэтому обе стороны выражения должны оцениваться перед использованием оператора, поэтому в случаях 2 и 4 обе стороны оператор всегда оценивается .
Разница между случаями 1 и 3 основана на логике короткого замыкания.
В случае 1 оператор &&
во втором выражении замыкается как false
на первое false
, в результате чего вторая половина выражения не выполняется быть оцененным.
В случае 3 false
в первой половине второго выражения приводит к вычислению второй половины выражения, увеличивая i
. ложь || expr
может быть только false
, если expr
также ложно (поэтому оно должно быть вычислено).