Различия в булевых операторах: & vs && и | vs ||

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

Ответ 1

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

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, вызывая исключение.

Ответ 2

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

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

Оценка короткого замыкания, минимальная оценка или оценка Маккарти (после Джона Маккарти) - это семантика некоторых логических операторов в некоторых языках программирования, в которых второй аргумент выполняется или оценивается, только если первого аргумента недостаточно определить значение выражения: когда первый аргумент функции AND оценивается как ложное, общее значение должно быть ложным; и когда первый аргумент функции OR оценивается как true, общее значение должно быть истинным.

Небезопасно означает, что оператор всегда проверяет каждое условие в предложении, поэтому в приведенных выше примерах 1/x может оцениваться, когда значение x на самом деле равно 0, вызывая исключение.

Ответ 3

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

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

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 не будет вычислено.

Побитовое И: Побитовое И использует оператор &. Он использовался для предварительной побитовой операции над значением. Намного легче понять, что происходит, если посмотреть на операцию над двоичными числами 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.

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

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

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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

если ((a < 0) && (b < 0)) {...} или аналогично, если ((a < 0) || (b < 0)) {...}

source: java programming lang 4th ed

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

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

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

Пример:

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

Это напечатает я = 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);

Но это напечатает я = 26; J = 26,

Ответ 10

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

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

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

Похожие для | и ||.

Ответ 11

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

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

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

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

Для второй точки см. этот пример:

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

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

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

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

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

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

Ответ 12

二进制 模拟 加法 操作, 先 加 不 进 位 得 А, 然后 算 进 位 得 В, 然后 (B << 1) +A 即 得到 两个 数 之 和.A 可以 由 两个 数 的 ^ 得到, В 可以 有 & B得到.

int plus(int num1,int num2){
if(num2==0) return num1;
return plus(num1^num2,(num1&num2)<<1);}