Другие ответы хорошо справились с задачей по рассмотрению функциональных различий между операторами, но ответы могут относиться практически ко всем существующим на сегодняшний день C-производным языкам.Вопрос помечен java , и поэтому я постараюсь ответить конкретно и технически за язык Java.
&
и |
могут быть либо целочисленными побитовыми операторами, либо логическимиЛогические операторы.Синтаксис для побитовых и логических операторов ( §15.22 ):
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
Синтаксис для EqualityExpression
определен в §15.21 , для которого требуется RelationalExpression
определено в §15.20 , что, в свою очередь, требует ShiftExpression
и ReferenceType
, определенных в §15.19 и §4.3 соответственно.Для ShiftExpression
требуется AdditiveExpression
, определенное в §15.18 , которое продолжает детализацию, определяя основные арифметические, унарные операторы и т. Д. ReferenceType
детализирует все различные способы представления типа.(Хотя ReferenceType
не включает в себя примитивные типы, в конечном итоге требуется определение примитивных типов, поскольку они могут быть типом измерения для массива, который равен a ReferenceType
.)
Битовые и логические операторы имеют следующие свойства:
- Эти операторы имеют различный приоритет,
&
имеет самый высокий приоритет и |
самый низкий приоритет. - Каждый из этих операторов синтаксически левоассоциативен (каждая группа слева направо).
- Каждый оператор коммутативен, если выражения операндов не имеют побочных эффектов.
- Каждый оператор ассоциативен.
- Битовые и логические операторы могут использоваться для сравнения двух операндов числового типа или двух операндов типа
boolean
.Все остальные случаи приводят к ошибке времени компиляции.
Различие между тем, является ли оператор побитовым или логическим, зависит от того, являются ли операнды «конвертируемыми впримитивный целочисленный тип "( §4.2 ) или, если они имеют типы boolean
или Boolean
( §5.1.8 ).
Если операндыявляются целочисленными типами, двоичное числовое продвижение ( §5.6.2 ) выполняется для обоих операндов, оставляя их обоих либо long
с, либо int
с для операции.Тип операции будет типом (повышенных) операндов.В этот момент &
будет побитовым И, ^
будет побитовым исключающим ИЛИ, а |
будет побитовым ИЛИ.( §15.22.1 )
Если операндами являются boolean
или Boolean
, операнды при необходимости будут преобразованы в распаковку ( §5.1.8 ), а тип операции будет boolean
.&
приведет к true
, если оба операнда true
, ^
приведет к true
, если оба операнда различны, и |
приведет к true
, если любой из операндов true
.( §15.22.2 )
Напротив, &&
- это «оператор условных операторов» ( §15.23 ) и ||
является «оператором условного или» ( §15.24 ).Их синтаксис определен следующим образом:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&
похож на &
, за исключением того, что он оценивает правый операнд, только если левый операнд равен true
.||
похож на |
, за исключением того, что он оценивает правый операнд, только если левый операнд равен false
.
Условно-И имеет следующие свойства:
- Условный оператор and синтаксически левоассоциативен (он группируется слева направо).
- Условный оператор and полностью ассоциативен в отношении как побочных эффектов, так и значения результата.То есть для любых выражений
a
, b
и c
вычисление выражения ((a) && (b)) && (c)
дает тот же результат с теми же побочными эффектами, возникающими в том же порядке, что и вычисление выражения (a) && ((b) && (c))
. - Каждый операнд оператора условного оператора and должен иметь тип
boolean
или Boolean
, иначе произойдет ошибка времени компиляции. - Типpe выражения условного оператора and всегда равно
boolean
. - Во время выполнения выражение левого операнда вычисляется первым;если результат имеет тип
Boolean
, он подвергается распаковке преобразования ( §5.1.8 ). - Если результирующее значение равно
false
, значение условного-ивыражение - false
, а выражение правого операнда не вычисляется. - Если значение левого операнда равно
true
, то вычисляется правое выражение;если результат имеет тип Boolean
, он подвергается распаковке без преобразования ( §5.1.8 ).Результирующее значение становится значением условного выражения и выражения. - Таким образом,
&&
вычисляет тот же результат, что и &
для boolean
операндов.Он отличается только тем, что выражение правого операнда вычисляется условно, а не всегда.
Условно-Или имеет следующие свойства:
- Условный оператор или синтаксически является левоассоциативным (он группируется слева направо).
- Условный оператор или полностью ассоциативен в отношении как побочных эффектов, так и значения результата.То есть для любых выражений
a
, b
и c
оценка выражения ((a) || (b)) || (c)
дает тот же результат с теми же побочными эффектами, возникающими в том же порядке, что и оценка выражения (a) || ((b) || (c))
. - Каждый операнд условного оператора или должен иметь тип
boolean
или Boolean
, иначе возникает ошибка времени компиляции. - Типусловное выражение или всегда равно
boolean
. - Во время выполнения выражение левого операнда вычисляется первым;если результат имеет тип
Boolean
, он подвергается распаковке преобразования ( §5.1.8 ). - Если результирующее значение равно
true
, значение условного иливыражение - true
, а выражение правого операнда не вычисляется. - Если значение левого операнда равно
false
, то вычисляется правое выражение;если результат имеет тип Boolean
, он подвергается распаковке ( §5.1.8 ).Результирующее значение становится значением условного выражения или. - Таким образом,
||
вычисляет тот же результат, что и |
для boolean
или Boolean
операндов.Он отличается только тем, что выражение правого операнда оценивается условно, а не всегда.
Вкратце, как @JohnMeagher неоднократно указывал в комментариях, &
и |
фактически являются логическими операторами без короткого замыкания в конкретном случае, когда операнды либо boolean
, либо Boolean
.С хорошими практиками (то есть: никакие вторичные эффекты), это незначительная разница.Однако когда операнды не boolean
с или Boolean
с, операторы ведут себя очень по-разному: побитовые и логические операции просто не очень хорошо сравниваются на высоком уровне программирования Java.