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);

}

10 ответов

Решение

&& а также || операторы "замыкают накоротко", то есть они не оценивают правую сторону, если в этом нет необходимости.

& а также | операторы, когда используются как логические операторы, всегда оценивают обе стороны.

Существует только один случай короткого замыкания для каждого оператора, и они:

  • false && ... - не обязательно знать, что такое правая сторона, результат должен быть false
  • true || ... - не обязательно знать, что такое правая сторона, результат должен быть 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;
}

Во второй версии используется оператор без короткого замыкания & и бросит 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 && True

В случае && нам нужно, чтобы обе стороны были True. Таким образом, если левая сторона является ложной, нет смысла проверять правую сторону, ответ должен быть ложным. И, следовательно, это не будет проверяться вообще.

Проще говоря, короткое замыкание означает прекращение оценки, когда вы знаете, что ответ больше не может измениться. Например, если вы оцениваете цепочку логических ANDи вы обнаружите FALSE в середине этой цепочки вы знаете, что результат будет ложным, независимо от того, каковы значения остальных выражений в цепочке. То же самое касается цепи ORs: как только вы обнаружите TRUEВы сразу знаете ответ и можете пропустить оценку остальных выражений.

Вы указываете Java, что вы хотите короткого замыкания с помощью && вместо & а также || вместо |, Первый набор в вашем посте - это короткое замыкание.

Обратите внимание, что это больше, чем попытка сохранить несколько циклов ЦП: в таких выражениях

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

короткое замыкание означает разницу между правильной работой и падением (в случае, когда mystring имеет значение null).

boolean a = (x < z) && (x == x);

Этот вид будет короткого замыкания, а это означает, что если (x < z) оценивается как ложный, тогда последний не оценивается, a будет ложным, в противном случае && также оценит (x == x),

& является побитовым оператором, но также логическим оператором AND, который не закорачивает.

Вы можете проверить их следующим образом (посмотрите, сколько раз метод вызывается в каждом случае):

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()) { }
}

Есть несколько различий между & а также && операторы. Те же различия относятся к | а также ||, Самое важное, что нужно иметь в виду, это то, что && является логическим оператором, который применяется только к булевым операндам, в то время как & является побитовым оператором, который применяется как к целочисленным типам, так и к логическим.

С помощью логической операции вы можете сделать короткое замыкание, потому что в некоторых случаях (например, первый операнд && являющийся 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 дает ноль, но у вас нет возможности узнать это без оценки обоих операндов.

Java предоставляет два интересных логических оператора, которых нет в большинстве других компьютерных языков. Эти вторичные версии AND и OR известны как логические операторы короткого замыкания. Как вы можете видеть из предыдущей таблицы, оператор ИЛИ возвращает true, когда A истинно, независимо от того, что B.

Точно так же оператор AND приводит к ложному, когда A ложно, независимо от того, что B. Если вы используете || а также && формы, а не | а также & В формах этих операторов Java не потрудится оценить только правый операнд. Это очень полезно, когда правый операнд зависит от того, является ли левый операнд истинным или ложным для правильной работы.

Например, следующий фрагмент кода показывает, как можно использовать преимущества логической оценки короткого замыкания, чтобы убедиться, что операция деления будет действительной до ее оценки:

if ( denom != 0 && num / denom >10)

С короткого замыкания формы И (&&), нет риска вызвать исключение деления на ноль во время выполнения. Если эта строка кода была написана с использованием одного & версия AND, обе стороны должны быть оценены, вызывая исключение во время выполнения, когда denom это ноль.

Обычной практикой является использование форм короткого замыкания И и ИЛИ в случаях, связанных с булевой логикой, при этом односимвольные версии оставляются исключительно для побитовых операций. Однако есть исключения из этого правила. Например, рассмотрим следующее утверждение:

 if ( c==1 & e++ < 100 ) d = 100;

Здесь, используя один & гарантирует, что операция приращения будет применена к e будь то c равно 1 или нет.

Логическое ИЛИ:- возвращает true, если хотя бы один из операндов оценивается как true. Оба операнда оцениваются перед применением оператора ИЛИ.

Короткое замыкание ИЛИ:- если левый операнд возвращает значение true, он возвращает истину без оценки правого операнда.

if(demon!=0&& num/demon>10)

Поскольку используется форма И (&&) для короткого замыкания, нет риска вызвать исключение во время выполнения, когда демон равен нулю.

Ссылка Ява 2 Пятое издание Герберта Шильдта

Документ из docs.oracle

Поскольку логические выражения оцениваются слева направо, они проверяются на возможное «короткое замыкание» вычисления с использованием следующих правил:

false && что-либо короткое замыкание оценивается как false.

правда || что-либо короткое замыкание оценивается как истинное.

Правила логики гарантируют, что эти оценки всегда правильны. Обратите внимание, что любая часть приведенных выше выражений не оценивается, поэтому любые побочные эффекты этого не вступают в силу.

https://docs.oracle.com/cd/E57185_01/HIRUG/ch31s05s01.html

Другие вопросы по тегам