где partialHits - это HashMap. Что произойдет, если первое утверждение истинно?Будет ли Java проверять второе утверждение? Потому что для того, чтобы первое утверждение было истинным, HashMap не должен содержать заданный ключ, поэтому, если второй оператор будет проверен, я получу NullPointerException. Итак, простыми словами, если у нас есть следующий код
if(a && b)
if(a || b)
будет ли Java проверять b, если a ложно в первом случае и если a верно во втором случае?
Если бы у нас не было "коротких замыканий" в Java, мы бы получили много исключений NullPointerExceptions в приведенных выше строках кода.
Ответ 2 · рейтинг 70 · Hardcoded
В Java есть 5 различных логических операторов сравнения: &, &&, |, ||, ^
& и && являются операторами "и", | и || операторы "или", ^ - "xor"
Одиночные будут проверять каждый параметр, независимо от значений, перед проверкой значений параметров. Двойные сначала проверят левый параметр и его значение, и если true (||) или false (&&) оставят второй нетронутым. Звук компилированный? Простой пример должен прояснить это:
Приведено для всех примеров:
String aString = null;
И:
if (aString != null & aString.equals("lala"))
Оба параметра проверяются перед выполнением оценки, и для второго параметра будет выброшено исключение NullPointerException.
if (aString != null && aString.equals("lala"))
Первый параметр проверяется, и он возвращает false, поэтому второй параметр не будет проверяться, потому что результат в любом случае будет false.
То же для OR:
if (aString == null | !aString.equals("lala"))
Также вызовет исключение NullPointerException.
if (aString == null || !aString.equals("lala"))
Первый параметр проверяется, и он возвращает true, поэтому второй параметр не будет проверяться, потому что результат в любом случае будет true.
XOR нельзя оптимизировать, потому что он зависит от обоих параметров.
Ответ 3 · рейтинг 27 · Peter van der Heijden
Нет, проверять не будем. Такое поведение называется оценкой короткого замыкания и является функцией многих языков, включая Java.
Ответ 4 · рейтинг 20 · Cowan
Все ответы здесь прекрасны, но, чтобы проиллюстрировать, откуда это взялось, для подобных вопросов полезно обратиться к источнику: Спецификации языка Java.
Оператор && подобен & (§15.22.2), но вычисляет свой правый операнд, только если значение его левого операнда истинно. [...] Во время выполнения сначала оценивается выражение левого операнда [...], если результирующее значение ложно, значение условного выражения и выражения ложно, а выражение правого операнда не оценивается . Если значение левого операнда истинно, тогда вычисляется правое выражение [...], результирующее значение становится значением условного выражения и. Таким образом, && вычисляет тот же результат, что и & для логических операндов. Он отличается только тем, что выражение правого операнда вычисляется условно, а не всегда.
|| оператор похож на | (§15.22.2), но оценивает свой правый операнд, только если значение его левого операнда ложно. [...] Во время выполнения сначала вычисляется выражение левого операнда; [...] если результирующее значение истинно, значение выражения условного ИЛИ истинно, а выражение правого операнда не оценивается. Если значение левого операнда ложно, то вычисляется правое выражение; [...] результирующее значение становится значением условного или выражения. Таким образом, || вычисляет тот же результат, что и | для логических или логических операндов. Он отличается только тем, что выражение правого операнда вычисляется условно, а не всегда.
Возможно, немного повторяется, но это лучшее подтверждение того, как именно они работают. Точно так же условный оператор (? :) оценивает только соответствующую "половину" (левая половина, если значение истинно, правая половина, если оно ложно), что позволяет использовать такие выражения, как:
int x = (y == null) ? 0 : y.getFoo();
без исключения NullPointerException.
Ответ 5 · рейтинг 9 · user3211238
Короткое замыкание здесь означает, что второе условие не будет оцениваться.
Если (A && B) приведет к короткому замыканию, если A имеет значение False.
Если (A && B) не приведет к короткому замыканию, если A истинно.
Если (A || B) приведет к короткому замыканию, если A истинно.
Если (A || B) не приведет к короткому замыканию, если A имеет значение False.
Ответ 6 · рейтинг 7 · Romain Linsolas
Нет, если a истинно (в проверке or), b не будет проверяться, так как результат проверки всегда будет истинным, каким бы ни было значение выражения b.
Сделайте простой тест:
if (true || ((String) null).equals("foobar")) {
...
}
не будет NullPointerException!
Ответ 7 · рейтинг 4 · abyx
Нет, не будет, Java произведет короткое замыкание и прекратит оценку, как только узнает результат.
Ответ 8 · рейтинг 4 · fortran
Да, оценка короткого замыкания для логических выражений является поведением по умолчанию во всем семействе C-подобных.
Интересным фактом является то, что Java также использует & и | в качестве логических операндов (они перегружены, с типами int они являются ожидаемыми побитовыми операциями) для оценки всех терминов в выражении, что также полезно, когда вам нужны побочные эффекты .
Ответ 9 · Peter Lawrey
Это восходит к основному различию между & и &&, | и ||
Кстати, вы выполняете одни и те же задачи много раз. Не уверен, что проблема в эффективности. Вы можете удалить часть дублирования.
Z z2 = partialHits.get(req_nr).get(z); // assuming a value cannout be null.
Z z3 = tmpmap.get(z); // assuming z3 cannot be null.
if(z2 == null || z2 < z3){
partialHits.get(z).put(z, z3);
}