Другие ответы хорошо справились с функциональной разницей между операторами, но ответы могут относиться практически ко всем существующим на сегодняшний день C-производным языкам. Вопрос отмеченЯваи поэтому я постараюсь ответить конкретно и технически за язык 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
не включает в себя примитивные типы, определение примитивных типов, в конечном счете требуется, так как они могут быть типом измерения для массива, который являетсяReferenceType
.)
Битовые и логические операторы имеют следующие свойства:
- Эти операторы имеют различный приоритет, с
&
самым высоким приоритетом и |
самым низким приоритетом.
- Каждый из этих операторов синтаксически левоассоциативен (каждая группа слева направо).
- Каждый оператор является коммутативным, если выражения операндов не имеют побочных эффектов.
- Каждый оператор ассоциативный.
- Побитовые и логические операторы могут использоваться для сравнения двух операндов числового типа или двух операндов типа
boolean
. Все остальные случаи приводят к ошибке времени компиляции.
Различие между тем, служит ли оператор как побитовый оператор или логическим оператором, зависит от того, являются ли операнды «конвертируемыми в примитивный целочисленный тип» ( §4.2 ) или они имеют типы boolean
или Boolean
( §5.1.8 ).
Если операнды являются целочисленными типами, двоичное числовое продвижение ( §5.6.2 ) выполняется для обоих операндов, оставляя их как long
s или int
s для операции. Тип операции будет типом (повышенных) операндов. В этот момент &
будет побитовое И, ^
будет побитовое исключающее ИЛИ и |
будет побитовое ИЛИ. ( §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 синтаксически левоассоциативен (он группируется слева направо).
- Оператор условного оператора и является полностью ассоциативным в отношении как побочных эффектов, так и значения результата. То есть для любых выражений
a
, b
и c
, оценка выражения ((a) && (b)) && (c)
дает тот же результат, с теми же побочными эффектами, возникающими в том же порядке, что и оценка выражения (a) && ((b) && (c))
.
- Каждый операнд условного оператора and должен иметь тип
boolean
или Boolean
, или возникает ошибка времени компиляции.
- Тип условного выражения и выражения всегда
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
s или Boolean
s, операторы ведут себя очень по- разному: побитовые и логические операции просто не сравниваются на высоком уровне программирования Java.