Las otras respuestas han hecho un buen trabajo al cubrir la diferencia funcional entre los operadores, pero las respuestas podrían aplicarse a casi todos los lenguajes derivados de C que existen en la actualidad. La pregunta está etiquetada conJava, por lo que me esforzaré por responder específica y técnicamente para el lenguaje Java.
&
y |
pueden ser operadores enteros a nivel de bit u operadores lógicos booleanos. La sintaxis para los operadores lógicos y a nivel de bits ( §15.22 ) es:
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
La sintaxis para EqualityExpression
se define en §15.21 , que requiere RelationalExpression
definido en §15.20 , que a su vez requiere ShiftExpression
y ReferenceType
definido en §15.19 y §4.3 , respectivamente. ShiftExpression
requiere AdditiveExpression
definido en §15.18 , que continúa profundizando, definiendo la aritmética básica, operadores unarios, etc. ReferenceType
profundiza en todas las diversas formas de representar un tipo. (Si bien ReferenceType
no incluye los tipos primitivos, la definición de los tipos primitivos se requiere en última instancia, ya que pueden ser el tipo de dimensión para una matriz, que es a ReferenceType
.)
Los operadores lógicos y a nivel de bit tienen las siguientes propiedades:
- Estos operadores tienen precedencia diferente, con
&
la precedencia más alta y |
la precedencia más baja.
- Cada uno de estos operadores es sintácticamente asociativo a la izquierda (cada grupo se agrupa de izquierda a derecha).
- Cada operador es conmutativo si las expresiones de operando no tienen efectos secundarios.
- Cada operador es asociativo.
- Los operadores lógicos y de bits pueden usarse para comparar dos operandos de tipo numérico o dos operandos de tipo
boolean
. Todos los demás casos dan como resultado un error en tiempo de compilación.
La distinción entre si el operador sirve como operador bit a bit o como operador lógico depende de si los operandos son "convertibles a un tipo integral primitivo" ( §4.2 ) o si son de tipos boolean
o Boolean
( §5.1.8 ).
Si los operandos son tipos integrales, promoción numérica binaria ( §5.6.2 ) se lleva a cabo en los dos operandos, dejando a los dos, ya sea como long
s o int
s para la operación. El tipo de la operación será el tipo de los operandos (promocionados). En ese punto, &
será bit a bit AND, ^
será bit a bit exclusivo, y |
será bit a bit inclusivo. ( §15.22.1 )
Si los operandos son boolean
o Boolean
, los operandos estarán sujetos a la conversión de unboxing si es necesario ( §5.1.8 ), y el tipo de operación será boolean
. &
dará como resultado true
si ambos operandos son true
, ^
dará como resultado true
si ambos operandos son diferentes, y |
dará como resultado true
si cualquiera de los operandos es true
. ( §15.22.2 )
Por el contrario, &&
es el "Operador condicional y" ( §15.23 ) y ||
es el "Operador condicional u" ( §15.24 ). Su sintaxis se define como:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&
es como &
, excepto que solo evalúa el operando derecho si el operando izquierdo es true
. ||
es como |
, excepto que solo evalúa el operando derecho si el operando izquierdo es false
.
Condicional-Y tiene las siguientes propiedades:
- El operador condicional y es sintácticamente asociativo a la izquierda (agrupa de izquierda a derecha).
- El operador condicional y es totalmente asociativo con respecto a los efectos secundarios y al valor del resultado. Es decir, para cualquier expresión
a
, b
y c
, la evaluación de la expresión ((a) && (b)) && (c)
produce el mismo resultado, con los mismos efectos secundarios que ocurren en el mismo orden, que la evaluación de la expresión (a) && ((b) && (c))
.
- Cada operando del operador condicional y debe ser de tipo
boolean
o Boolean
, o se produce un error en tiempo de compilación.
- El tipo de condicional y expresión es siempre
boolean
.
- En tiempo de ejecución, la expresión del operando de la izquierda se evalúa primero; si el resultado tiene tipo
Boolean
, está sujeto a la conversión de unboxing ( §5.1.8 ).
- Si el valor resultante es
false
, el valor de condicional y expresión es false
y la expresión de operando de la derecha no se evalúa.
- Si el valor del operando de la izquierda es
true
, entonces se evalúa la expresión de la derecha; si el resultado tiene tipo Boolean
, está sujeto a la conversión de unboxing ( §5.1.8 ). El valor resultante se convierte en el valor de condicional y expresión.
- Por lo tanto,
&&
calcula el mismo resultado que &
en los boolean
operandos. Solo difiere en que la expresión del operando de la derecha se evalúa condicionalmente en lugar de siempre.
Condicional-Or tiene las siguientes propiedades:
- El operador condicional u es sintácticamente asociativo a la izquierda (agrupa de izquierda a derecha).
- El operador condicional u es totalmente asociativo con respecto a los efectos secundarios y al valor del resultado. Es decir, para cualquier expresión
a
, b
y c
, la evaluación de la expresión ((a) || (b)) || (c)
produce el mismo resultado, con los mismos efectos secundarios que ocurren en el mismo orden, que la evaluación de la expresión (a) || ((b) || (c))
.
- Cada operando del condicional-u operador debe ser de tipo
boolean
o Boolean
, o se produce un error en tiempo de compilación.
- El tipo de una condicional-o expresión es siempre
boolean
.
- En tiempo de ejecución, la expresión del operando de la izquierda se evalúa primero; si el resultado tiene tipo
Boolean
, está sujeto a la conversión de unboxing ( §5.1.8 ).
- Si el valor resultante es
true
, el valor de la expresión condicional o es true
y la expresión del operando de la derecha no se evalúa.
- Si el valor del operando de la izquierda es
false
, entonces se evalúa la expresión de la derecha; si el resultado tiene tipoBoolean
, está sujeto a la conversión de unboxing ( §5.1.8 ). El valor resultante se convierte en el valor de la condicional o expresión.
- Por lo tanto,
||
calcula el mismo resultado que |
en boolean
oBoolean
operandos. Solo difiere en que la expresión del operando de la derecha se evalúa condicionalmente en lugar de siempre.
En resumen, como @JohnMeagher ha señalado repetidamente en los comentarios, &
y |
son, de hecho, operadores booleanos sin cortocircuito en el caso específico de que los operandos sean boolean
o Boolean
. Con buenas prácticas (es decir: sin efectos secundarios), esta es una diferencia menor. Sin embargo, cuando los operandos no son boolean
s o Boolean
s, los operadores se comportan de manera muy diferente: las operaciones bit a bit y lógicas simplemente no se comparan bien en el alto nivel de programación Java.