Различия в логических операторах: & vs && и |против || - PullRequest
99 голосов
/ 25 октября 2010

Я знаю правила для && и ||, но что такое & и |? Пожалуйста, объясните мне это на примере.

Ответы [ 11 ]

122 голосов
/ 25 октября 2010

Это операторы побитового И и побитового ИЛИ.

int a = 6; // 110
int b = 4; // 100

// Bitwise AND    

int c = a & b;
//   110
// & 100
// -----
//   100

// Bitwise OR

int d = a | b;
//   110
// | 100
// -----
//   110

System.out.println(c); // 4
System.out.println(d); // 6

Спасибо Карлосу за то, что он указал на соответствующий раздел в Спецификации языка Java ( 15.22.1 , 15.22.2 ) относительно различных действий оператора на основе его входных данных.

Действительно, когда оба входа булевы, операторы считаются логическими логическими операторами и ведут себя подобно операторам Условного-И (&&) и Условного-ИЛИ (||), за исключением того факта, что они не короткое замыкание, поэтому при соблюдении следующих правил:

if((a != null) && (a.something == 3)){
}

Это не:

if((a != null) & (a.something == 3)){
}

«Короткое замыкание» означает, что оператор не обязательно проверяет все условия. В приведенных выше примерах && будет проверять второе условие только в том случае, если a не равно null (в противном случае весь оператор вернет false, и в любом случае будет бесполезно проверять следующие условия), поэтому утверждение a.something не вызывает исключение или считается "безопасным".

Оператор & всегда проверяет каждое условие в предложении, поэтому в приведенных выше примерах a.something может оцениваться, когда a фактически является значением null, вызывая исключение.

101 голосов
/ 25 октября 2010

Я думаю, вы говорите о логическом значении обоих операторов, здесь у вас есть таблица-резюме:

boolean a, b;

Operation     Meaning                       Note
---------     -------                       ----
   a && b     logical AND                    short-circuiting
   a || b     logical OR                     short-circuiting
   a &  b     boolean logical AND            not short-circuiting
   a |  b     boolean logical OR             not short-circuiting
   a ^  b     boolean logical exclusive OR
  !a          logical NOT

short-circuiting        (x != 0) && (1/x > 1)   SAFE
not short-circuiting    (x != 0) &  (1/x > 1)   NOT SAFE
23 голосов
/ 08 апреля 2016

Я знаю, что здесь много ответов, но все они кажутся немного запутанными.Поэтому, проведя некоторое исследование из руководства по изучению Java-оракула, я пришел к трем различным сценариям, когда использовать && или &.Три сценария: логическое И , побитовое И и логическое И .

Логическое И: Логическое И (или условное AND) использует оператор && .Это короткозамкнутый смысл: если левый операнд имеет значение false, то правый операнд не будет оцениваться.
Пример:

int x = 0;
if (false && (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); // "0"

В приведенном выше примере значение, выводимое на консоль x, будет 0, поскольку первый операнд в операторе if равен false, следовательно, java не нужно вычислять (1== ++ x) поэтому x не будет вычисляться.

Побитовое И: Побитовое И использует оператор & .Используется для предварительной побитовой операции со значением.Гораздо проще увидеть, что происходит, посмотрев на операцию над двоичными числами, например:

int a = 5;     //                    5 in binary is 0101
int b = 12;    //                   12 in binary is 1100
int c = a & b; // bitwise & preformed on a and b is 0100 which is 4

Как вы можете видеть на примере, когда двоичные представления чисел 5 и 12 выстроены в ряд, тогдапоразрядное И предварительно сгенерирует только двоичное число, где одна и та же цифра в обоих числах имеет 1. Следовательно, 0101 & 1100 == 0100. Которое в десятичном числе 5 & 12 == 4.

Логическое И: Теперь логический оператор AND ведет себя аналогично и по-разному как для побитового И, так и для логического И.Мне нравится думать о нем как о предварительном формировании побитового И между двумя логическими значениями (или битами), поэтому он использует оператор & .Логические значения также могут быть результатом логического выражения.

Возвращает либо истинное, либо ложное значение, очень похожее на логическое И, но в отличие от логического И оно не закорочено.Причина в том, что для того, чтобы преформировать это побитовое И, он должен знать значение как левого, так и правого операнда.Вот пример:

int x = 0;
if (false & (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); //"1"

Теперь, когда этот оператор if выполняется, выражение (1 == ++ x) будет выполнено, даже если левый операнд имеет значение false.Следовательно, значение, распечатанное для x, будет равно 1, поскольку оно было увеличено.

Это также относится к логическому ИЛИ (||), побитовому ИЛИ (|) и логическому ИЛИ (|).

7 голосов
/ 25 октября 2010

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

5 голосов
/ 25 октября 2010

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

2 голосов
/ 05 марта 2015

В Java одиночные операторы &, |, ^,! зависит от операндов. Если оба операнда являются целочисленными, то выполняется побитовая операция. Если оба являются логическими значениями, выполняется «логическая» операция.

Если оба операнда не совпадают, генерируется ошибка времени компиляции.

Двойные операторы &&, || ведут себя так же, как их одиночные аналоги, но оба операнда должны быть условными выражениями, например:

if ((a <0) && (b <0)) {...} или аналогично, if ((a <0) || (b <0)) {...} </p>

источник: язык программирования Java 4-е изд

1 голос
/ 15 июня 2015

&&;||являются логическими операторами .... короткое замыкание

&;|являются логическими логическими операторами .... Не короткое замыкание

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

Например:

int i = 25;
int j = 25;
if(i++ < 0 && j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Это выведет i = 26;j = 25, так как первое условие ложно, условие правой руки игнорируется, поскольку результат в любом случае ложен, независимо от условия правой стороны. (короткое замыкание)

int i = 25;
int j = 25;
if(i++ < 0 & j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Но это выдает i =26;J = 26

1 голос
/ 04 сентября 2013

Может быть, полезно знать, что побитовые операторы И и побитовые ИЛИ всегда вычисляются перед тем, как условное И и условное ИЛИ используются в одном и том же выражении.

if ( (1>2) && (2>1) | true) // false!
1 голос
/ 25 октября 2010

& и | - побитовые операторы для целочисленных типов (например, int): http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

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

0 голосов
/ 09 декабря 2014

Хотя основное различие заключается в том, что & используется для побитовых операций, в основном на long, int или byte, где она может использоваться для вида маски, результаты могут отличаться, даже если вы ее используетевместо логического &&.

Разница более заметна в некоторых сценариях:

  1. Оценка некоторых выражений занимает много времени
  2. Оценка одного из выраженийможет быть сделано, только если предыдущее было истинно
  3. У выражений есть некоторый побочный эффект (предназначенный или нет)

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

Второй пункт см. В этом примере:

if ((a != null) & (a.isEmpty()))

Этотерпит неудачу для null, так как при вычислении второго выражения получается NullPointerException.Логический оператор && является ленивым, если левый операнд равен false, результат равен false независимо от того, какой правый операнд.

Пример для третьего пункта - скажем, у нас есть приложение, которое использует DB без каких-либо триггеровили каскады.Прежде чем мы удалим объект здания, мы должны изменить здание объекта отдела на другое.Допустим также, что статус операции возвращается как логическое значение (true = success).Затем:

if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))

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

Что касается a || b, это эквивалентно !(!a && !b), он останавливается, если a истинно, объяснений не требуется.

...