Inne odpowiedzi wykonały dobrą robotę, pokrywając różnicę funkcjonalną między operatorami, ale odpowiedzi mogą dotyczyć niemal każdego istniejącego obecnie języka C. Pytanie jest oznaczone tagiemJawa, więc postaram się odpowiedzieć konkretnie i technicznie na język Java.
&
i |
mogą być albo całkowitymi bitowymi operatorami, albo logicznymi operatorami logicznymi. Składnia dla operatorów bitowych i logicznych ( §15.22 ) jest następująca:
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
Składnia EqualityExpression
jest zdefiniowana w § 15.21 , który wymaga RelationalExpression
zdefiniowania w § 15.20 , który z kolei wymaga ShiftExpression
i ReferenceType
zdefiniowany odpowiednio w §15.19 i §4.3 . ShiftExpression
wymaga AdditiveExpression
zdefiniowanego w § 15.18 , który kontynuuje drążenie w dół, definiując podstawowe arytmetyki, operatory jednoargumentowe itp. drążyReferenceType
wszystkie różne sposoby reprezentowania typu. (Chociaż ReferenceType
nie obejmuje typów pierwotnych, ostatecznie jest wymagana definicja typów pierwotnych, ponieważ mogą one być typem wymiaru tablicy, którym jest a ReferenceType
.)
Operatory bitowe i logiczne mają następujące właściwości:
- Operatory te mają różny priorytet, przy
&
czym mają najwyższy i |
najniższy priorytet.
- Każdy z tych operatorów jest składniowo lewostronny (każda grupa od lewej do prawej).
- Każdy operator jest przemienny, jeśli wyrażenia operandu nie mają skutków ubocznych.
- Każdy operator jest skojarzony.
- Operatory bitowe i logiczne mogą być użyte do porównania dwóch operandów typu numerycznego lub dwóch operandów typu
boolean
. Wszystkie pozostałe przypadki powodują błąd czasu kompilacji.
Rozróżnienie, czy operator służy jako operator bitowe lub operator logiczny zależy od tego, czy są to argumenty „przekształcić w pierwotnej integralną typu” ( §4.2 ), czy są one typu boolean
lub Boolean
( §5.1.8 ).
Jeśli operandy są typami integralnymi, promocja binarna numeryczna ( § 5.6.2 ) jest wykonywana na obu operandach, pozostawiając je jako long
s lub int
s dla operacji. Typ operacji będzie typem (promowanych) operandów. W tym momencie &
będzie bitowe ORAZ, ^
będzie bitowo wykluczające LUB, i |
będzie bitowo włącznie LUB. ( §15.22.1 )
Jeśli operandy są boolean
lub Boolean
, operandy zostaną poddane konwersji rozpakowywania, jeśli to konieczne ( §5.1.8 ), a typem operacji będzie boolean
. &
spowoduje, true
jeśli oba operandy są true
, ^
spowoduje, true
że oba operandy będą różne, i |
spowoduje, true
że którykolwiek z nich jest true
. ( §15.22.2 )
Natomiast &&
jest „operatorem warunkowym” ( § 15.23 ) i ||
„operatorem warunkowym” ( §15.24 ). Ich składnia jest zdefiniowana jako:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&
jest podobny &
, z tym wyjątkiem, że ocenia prawy operand tylko wtedy, gdy lewy jest true
. ||
jest podobny |
, z tym wyjątkiem, że ocenia prawy operand tylko wtedy, gdy lewy jest false
.
Warunkowe-I ma następujące właściwości:
- Operator warunkowy i jest składniowo lewostronnie asocjatywny (grupuje od lewej do prawej).
- Operator warunkowy i operator jest w pełni asocjatywny zarówno pod względem skutków ubocznych, jak i wartości wyniku. To znaczy dla wszystkich wyrażeń
a
, b
a c
ocena wyrażenia ((a) && (b)) && (c)
daje ten sam wynik, z tymi samymi skutkami ubocznymi występującymi w tej samej kolejności, co ocena wyrażenia (a) && ((b) && (c))
.
- Każdy operand operatora warunkowego i operatora musi być typu
boolean
lub Boolean
, inaczej wystąpi błąd czasu kompilacji.
- Typ wyrażenia warunkowego i jest zawsze
boolean
.
- W czasie wykonywania najpierw oceniane jest wyrażenie po lewej stronie argumentu; jeśli wynik ma typ
Boolean
, jest poddawany konwersji rozpakowywania ( §5.1.8 ).
- Jeśli wartością wynikową jest
false
, wartość wyrażenia warunkowego i wyrażenia jest, false
a wyrażenie operandu po prawej stronie nie jest oceniane.
- Jeśli wartość lewego operandu wynosi
true
, wówczas ocenia się prawe wyrażenie; jeśli wynik ma typ Boolean
, jest poddawany konwersji rozpakowywania ( §5.1.8 ). Wynikowa wartość staje się wartością wyrażenia warunkowego i wyrażenia.
- W ten sposób
&&
oblicza ten sam wynik, co &
na boolean
operandach. Różni się tylko tym, że wyrażenie operandu po prawej stronie jest oceniane warunkowo, a nie zawsze.
Warunkowe-Lub ma następujące właściwości:
- Operator warunkowy lub jest składniowo lewostronnie asocjatywny (grupuje od lewej do prawej).
- Operator warunkowy lub operator jest w pełni asocjatywny zarówno pod względem skutków ubocznych, jak i wartości wyniku. To znaczy, dla wszystkich wyrażeń
a
, b
i c
ocena wyrażenia ((a) || (b)) || (c)
daje ten sam wynik, z tymi samymi skutkami ubocznymi występującymi w tej samej kolejności, co ocena wyrażenia (a) || ((b) || (c))
.
- Każdy operand operatora warunkowego lub operator musi być typu
boolean
lub Boolean
, inaczej wystąpi błąd kompilacji.
- Typem wyrażenia warunkowego lub jest zawsze
boolean
.
- W czasie wykonywania najpierw oceniane jest wyrażenie po lewej stronie argumentu; jeśli wynik ma typ
Boolean
, jest poddawany konwersji rozpakowywania ( §5.1.8 ).
- Jeśli wartością wynikową jest
true
, wartość wyrażenia warunkowego lub wyrażenia jest, true
a wyrażenie operandu po prawej stronie nie jest oceniane.
- Jeśli wartość lewego operandu wynosi
false
, wówczas ocenia się prawe wyrażenie; jeśli wynik ma typ Boolean
, jest poddawany konwersji rozpakowywania ( §5.1.8 ). Wynikowa wartość staje się wartością warunkowego lub wyrażenia.
- W ten sposób
||
oblicza ten sam wynik, co |
on boolean
lub Boolean
operandy. Różni się tylko tym, że wyrażenie operandu po prawej stronie jest oceniane warunkowo, a nie zawsze.
W skrócie, jak @JohnMeagher wielokrotnie zwracał uwagę w komentarzach, &
i |
są w rzeczywistości, bez zwierania operatorów logicznych w przypadku konkretnego z argumentów będących albo boolean
albo Boolean
. Przy dobrych praktykach (tj. Bez efektów wtórnych) jest to niewielka różnica. Gdy argumenty nie są boolean
S lub Boolean
s, jednak operatorzy zachowują się bardzo różnie: bitowe i operacje logiczne po prostu nie porównać również na wysokim poziomie programowania Java.