Короткое замыкание логического оператора Java
какой набор является коротким замыканием, и что именно означает, что сложное условное выражение является коротким замыканием?
public static void main(String[] args) {
int x, y, z;
x = 10;
y = 20;
z = 30;
// T T
// T F
// F T
// F F
//SET A
boolean a = (x < z) && (x == x);
boolean b = (x < z) && (x == z);
boolean c = (x == z) && (x < z);
boolean d = (x == z) && (x > z);
//SET B
boolean aa = (x < z) & (x == x);
boolean bb = (x < z) & (x == z);
boolean cc = (x == z) & (x < z);
boolean dd = (x == z) & (x > z);
}
9 ответов:
The
&&и||операторы "короткого замыкания", то есть они не оценивают правую сторону, если это не необходимо.The
&и|операторы, когда они используются в качестве логических операторов, всегда оценивают обе стороны.есть только один случай короткого замыкания для каждого оператора, а это:
false && ...- не обязательно знать, что такое правая сторона, результат должен бытьfalsetrue || ...- Не обязательно знать, что такое правая сторона, результат должен бытьtrueдавайте сравним поведение в простом примере:
public boolean longerThan(String input, int length) { return input != null && input.length() > length; } public boolean longerThan(String input, int length) { return input != null & input.length() > length; }2-я версия использует оператор без короткого замыкания
&и броситNullPointerExceptionеслиinputиnull, но 1-я версия вернетсяfalseбез исключения;
SET a использует булевы операторы короткого замыкания.
что означает "короткое замыкание" в контексте булевых операторов, так это то, что для набора булевых значений b1, b2,..., bn, версии короткого замыкания прекратят оценку, как только первое из этих булевых значений будет истинным (||) или ложным (&&).
например:
// 2 == 2 will never get evaluated because it is already clear from evaluating // 1 != 1 that the result will be false. (1 != 1) && (2 == 2) // 2 != 2 will never get evaluated because it is already clear from evaluating // 1 == 1 that the result will be true. (1 == 1) || (2 != 2)
короткое замыкание означает, что второй оператор не будет проверяться, если первый оператор решает конечный результат.
например выражение: True / / False
в случае ||, все что нам нужно это одна из сторон чтобы быть правдой. Поэтому, если левая сторона истинна, нет смысла проверять правую сторону, и, следовательно, это не будет проверено вообще.
Аналогично, False & & True
в случае&&, нам нужно обеих сторон, чтобы быть правдой. Поэтому, если левая сторона ложна, нет смысла проверять правую сторону, ответ должен быть ложным. И поэтому это вообще не будет проверяться.
boolean a = (x < z) && (x == x);этот вид будет короткое замыкание, что означает, если
(x < z)оценивает в false, то последний не оценивается,aбудет false, иначе&&также будет оценивать(x == x).
&является побитовым оператором, но также булевым и оператором, который не вызывает короткого замыкания.вы можете проверить их следующим образом (смотрите, сколько раз метод вызывается в каждом случае):
public static boolean getFalse() { System.out.println("Method"); return false; } public static void main(String[] args) { if(getFalse() && getFalse()) { } System.out.println("============================="); if(getFalse() & getFalse()) { } }
иными словами, короткое замыкание означает остановку оценки, как только вы знаете, что ответ больше не может измениться. Например, если вы оцениваете цепочку логических
ANDs и вы обнаружите aFALSEв середине этой цепи, вы знаете, результат будет ложным, независимо от того, каковы значения остальных выражений в цепочке. То же самое касается цепочкиORs: как только вы обнаружитеTRUE, вы знаете ответ сразу, и поэтому вы можете пропустить оценка остальных выражений.вы указываете Java, что вы хотите короткого замыкания с помощью
&&вместо&и||вместо|. Первый набор в вашем посте-короткое замыкание.обратите внимание, что это больше, чем попытка сохранить несколько циклов процессора: в выражениях, подобных этому
if (mystring != null && mystring.indexOf('+') > 0) { ... }короткое замыкание означает разницу между правильной работой и сбоем (в случае, когда mystring имеет значение null).
Java предоставляет два интересных логических оператора, не найденных в большинстве других компьютерных языков. Эти вторичные варианты и и или, известные как логические операторы короткого замыкания. Как вы можете видеть из предыдущей таблицы, оператор OR приводит к true, когда A истинно, независимо от того, что такое B.
аналогично, оператор AND приводит к false, когда A ложно, независимо от того, что такое B. Если вы используете
||и&&"формы", а не|и&формы этих операторов, Java не будет беспокоиться, чтобы оценить только правый операнд. Это очень полезно, когда правый операнд зависит от левого, являющегося истинным или ложным, чтобы функционировать должным образом.например, в следующем фрагменте кода показано, как можно воспользоваться логической оценкой короткого замыкания, чтобы убедиться, что операция деления будет действительна до ее оценки:
if ( denom != 0 && num / denom >10)так как форма короткого замыкания и (
&&) используется, нет никакого риска вызвать исключение времени выполнения от деления на ноль. Если эта строка кода была написана с помощью одного&версия AND, обе стороны должны быть оценены, вызывая исключение времени выполнения, когдаdenomравна нулю.стандартная практика заключается в использовании форм короткого замыкания и и или в случаях, связанных с булевой логикой, оставляя односимвольные версии исключительно для побитовых операций. Однако из этого правила есть исключения. Для например, рассмотрим следующее утверждение:
if ( c==1 & e++ < 100 ) d = 100;здесь, используя один
&гарантирует, что операция инкремента будет применена кeлиcравно 1 или нет.
Logical OR: - возвращает true, если хотя бы один из операндов имеет значение true. Оба операнда вычисляются перед применением оператора OR.
короткое замыкание или: - если левый операнд возвращает true,он возвращает true без оценки правого операнда.
if(demon!=0&& num/demon>10)Так как используется форма короткого замыкания AND (&&), нет никакого риска вызвать исключение времени выполнения, когда демон равен нулю.
Ref. Java 2 пятое издание Герберта Шильдта
есть несколько различий между
&и&&операторы. Те же различия относятся и к|и||. Самое главное, чтобы иметь в виду, что&&это логическое оператор, который применяется только к логическим операндам, в то время как&это побитовое оператор, который применяется как к целочисленным типам, так и к логическим.С логической операции, вы можете сделать короткое замыкание, потому что в некоторых случаях (как первый операнд
&&будучиfalse, или первый операнд||будучиtrue), вам не нужно оценивать остальную часть выражения. Это очень полезно для таких вещей, как проверкаnullперед доступом к файлу или методу и проверкой потенциальных нулей перед их делением. Для сложного выражения каждая часть выражения вычисляется рекурсивно таким же образом. Например, в следующем случае:(7 == 8) || ((1 == 3) && (4 == 4))только подчеркнул порции будут оценены. Чтобы вычислить
||, проверьте, если7 == 8иtrue. Если бы это было так, правая сторона была бы полностью пропущена. Правая сторона проверяет только если1 == 3иfalse. Так как это так,4 == 4не нужно проверять, и все выражение оценивается вfalse. Если бы левая сторона былаtrue, например,7 == 7вместо7 == 8, вся правая сторона будет пропущена, потому что весь||выражение будетtrueне обращающий внимания.при побитовой операции вам нужно оценить все операнды, потому что вы действительно просто объединяете биты. Булевы фактически являются одноразрядным целым числом в Java (независимо от того, как работают внутренние элементы), и это просто совпадение, что вы можете сделать короткое замыкание для побитовых операторов в этом частном случае. Причина в том, что вы не можете замкнуть общее целое число
&или|операция заключается в том, что некоторые биты могут быть включены, а некоторые могут быть выключены в любом операнд. Что-то вроде1 & 2дает ноль, но у вас нет способа узнать это без оценки обоих операндов.