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

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

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

 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 Language Spec ( 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 

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

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

 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.

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

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

 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 (|). Надеемся, что это устранит некоторую путаницу.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Например:

 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,

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

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

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

Похожие | и ||.

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

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

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

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

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

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

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

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

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

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

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

Давайте будем гением компьютера.