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

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

11 ответов


это побитовые и и побитовые операторы OR.

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 равен false, поэтому java не нужно вычислять (1 == ++x), поэтому x не будет вычисляться.

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

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.

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

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

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

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

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


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


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


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

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

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

if ((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.... Non-короткое замыкание

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

Например:

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. Логический оператор && ленив, если левый операнд ложен, результат ложен независимо от того, какой правый операнд.

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

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

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

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