Другие ответы хорошо справились с функциональной разницей между операторами, но ответы могут относиться практически ко всем существующим на сегодняшний день 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 ) выполняется для обоих операндов, оставляя их как longs или ints для операции. Тип операции будет типом (повышенных) операндов. В этот момент &будет побитовое И, ^будет побитовое исключающее ИЛИ и |будет побитовое ИЛИ. ( §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. С хорошими практиками (то есть: никакие вторичные эффекты), это незначительная разница. Однако, когда операнды не booleans или Booleans, операторы ведут себя очень по- разному: побитовые и логические операции просто не сравниваются на высоком уровне программирования Java.