Інші відповіді вдало вирішили розкрити функціональну різницю між операторами, але відповіді можуть стосуватися майже кожної окремо взятої мови С, яка існує сьогодні. Питання позначено тегом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
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
.
Умовно-А має такі властивості:
- Умовно-оператор синтаксично ліво-асоціативний (він групується зліва направо).
- Умовно-оператор є повністю асоціативним щодо побічних ефектів та значення результату. Тобто, для будь-яких виразів
a
, b
а також c
, оцінка виразу ((a) && (b)) && (c)
дає той самий результат із тими ж побічними ефектами, що виникають у тому ж порядку, що й оцінка виразу(a) && ((b) && (c))
.
- Кожен операнд умовного і оператора повинен бути типу
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
або Boolean
не, оператори поводяться зовсім інакше: побітові та логічні операції просто не дуже добре порівнюються на високому рівні програмування Java.