Различия в логические операторы: & против && и | против ||


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

11 91

11 ответов:

это побитовое и побитовое или операторов.

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

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

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

Я знаю, что здесь много ответов, но все они кажутся немного запутанными. Поэтому после проведения некоторых исследований из учебного руководства Java oracle я придумал три разных сценария использования && или &. Эти три сценария логические и,побитовое и и логическое и.

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

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

В приведенном выше примере значение, выводимое на консоль x, будет равно 0, поскольку первый операнд в операторе if является ложным, поэтому 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 ведет себя аналогично и по-разному как для побитового, так и для логического AND. Я как думать о нем, как исполняющую операцию побитового и между двумя логическими значениями (или бит), поэтому он использует & оператора. Логические значения также могут быть результатом логического выражения.

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

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

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

Это также относится к логическому или ( | / ), побитовому или ( | ) и логическому или (|) Надеюсь, это прояснит некоторую путаницу.

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

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

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

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

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

Если ((a

источник: java programming lang 4th ed

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

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

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

if ( (1>2) && (2>1) | true) // false!

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

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

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

Например:

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,

Если выражение с логическим & вычисляется оператор, вычисляются оба операнда. Затем к операнду применяется оператор&.

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

Если первый операнд возвращает значение true, то второй операнд вычисляется. Если второй операнд возвращает значение true, после чего оператор && применяется к первому и второму операндам.

аналогично для | и|/.

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

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

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

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

для второго пункта, см. Этот пример:

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

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

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

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

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

как a || b, это эквивалент !(!a && !b), оно прекращается, если a правда, больше никаких объяснений не требуется.