As outras respostas fizeram um bom trabalho ao cobrir a diferença funcional entre os operadores, mas as respostas podem se aplicar a praticamente todas as linguagens derivadas de C existentes hoje. A pergunta está marcada comJavae, por isso, tentarei responder específica e tecnicamente à linguagem Java.
&e |podem ser operadores inteiros bit a bit ou operadores lógicos booleanos. A sintaxe para os operadores bit a bit e lógicos ( §15.22 ) é:
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
A sintaxe para EqualityExpressioné definida no §15.21 , que requer RelationalExpressiondefinido no §15.20 , que por sua vez requer ShiftExpressione ReferenceTypedefinido nos §15.19 e §4.3 , respectivamente. ShiftExpressionOs requisitos AdditiveExpressiondefinidos no §15.18 , que continuam a detalhar, definindo a aritmética básica, os operadores unários, etc. detalham ReferenceTypetodas as várias maneiras de representar um tipo. (Embora ReferenceTypenão inclua os tipos primitivos, a definição de tipos primitivos é finalmente necessária, pois eles podem ser o tipo de dimensão para uma matriz, que é a ReferenceType.)
Os operadores bit a bit e lógicos têm as seguintes propriedades:
- Esses operadores têm precedência diferente, com
&a maior e |a menor precedência.
- Cada um desses operadores é sintaticamente associativo à esquerda (cada grupo da esquerda para a direita).
- Cada operador é comutativo se as expressões do operando não tiverem efeitos colaterais.
- Cada operador é associativo.
- Os operadores bit a bit e lógicos podem ser usados para comparar dois operandos do tipo numérico ou dois operandos do tipo
boolean. Todos os outros casos resultam em um erro em tempo de compilação.
A distinção entre se o operador serve como operador bit a bit ou operador lógico depende se os operandos são "conversíveis em um tipo integral primitivo" ( §4.2 ) ou se são do tipo booleanou Boolean( §5.1.8 ).
Se os operandos são do tipo integral, a promoção numérica binária ( §5.6.2 ) é realizada nos dois operandos, deixando-os como longs ou ints para a operação. O tipo da operação será o tipo dos operandos (promovidos). Nesse ponto, &será AND bit a bit, ^será OR bit a bit exclusivo e |será OR bit a bit, inclusive. ( §15.22.1 )
Se os operandos forem booleanou Boolean, os operandos estarão sujeitos à conversão de unboxing, se necessário ( §5.1.8 ), e o tipo da operação será boolean. &resultará em truese ambos os operandos forem true, ^resultará em truese ambos operandos forem diferentes e |resultará em truese qualquer operando for true. ( §15.22.2 )
Por outro lado, && é o "Operador condicional-E" ( §15.23 ) e ||é o " Operador condicional-E " ( §15.24 ). Sua sintaxe é definida como:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&é como &, exceto que ele avalia apenas o operando direito se o operando esquerdo estiver true. ||é como |, exceto que ele avalia apenas o operando direito se o operando esquerdo estiver false.
Condicional-E tem as seguintes propriedades:
- O operador condicional e é associativamente à esquerda sintaticamente (agrupa da esquerda para a direita).
- O operador condicional e é totalmente associativo em relação aos efeitos colaterais e ao valor do resultado. Ou seja, para qualquer expressão
a, be cavaliação da expressão ((a) && (b)) && (c)produz o mesmo resultado, com os mesmos efeitos colaterais ocorrendo na mesma ordem, como avaliação da expressão (a) && ((b) && (c)).
- Cada operando do operador condicional e deve ser do tipo
booleanou Boolean, ou ocorre um erro em tempo de compilação.
- O tipo de uma expressão condicional e é sempre
boolean.
- No tempo de execução, a expressão do operando do lado esquerdo é avaliada primeiro; se o resultado tiver um tipo
Boolean, ele estará sujeito à conversão de unboxing ( §5.1.8 ).
- Se o valor resultante for
false, o valor da expressão condicional e é falsee a expressão do operando do lado direito não é avaliada.
- Se o valor do operando do lado esquerdo for
true, a expressão do lado direito será avaliada; se o resultado tiver um tipo Boolean, ele estará sujeito à conversão de unboxing ( §5.1.8 ). O valor resultante se torna o valor da expressão condicional-e.
- Assim,
&&calcula o mesmo resultado que &nos booleanoperandos. Difere apenas no fato de a expressão do operando do lado direito ser avaliada condicionalmente, e não sempre.
Condicional-Or tem as seguintes propriedades:
- O operador condicional ou é associativamente à esquerda sintaticamente (agrupa da esquerda para a direita).
- O operador condicional ou é totalmente associativo em relação aos efeitos colaterais e ao valor do resultado. Ou seja, para qualquer expressão
a, be cavaliação da expressão ((a) || (b)) || (c)produz o mesmo resultado, com os mesmos efeitos colaterais ocorrendo na mesma ordem, como avaliação da expressão (a) || ((b) || (c)).
- Cada operando do operador condicional ou deve ser do tipo
booleanou Boolean, ou ocorre um erro em tempo de compilação.
- O tipo de uma expressão condicional ou é sempre
boolean.
- No tempo de execução, a expressão do operando do lado esquerdo é avaliada primeiro; se o resultado tiver um tipo
Boolean, ele estará sujeito à conversão de unboxing ( §5.1.8 ).
- Se o valor resultante for
true, o valor da expressão condicional ou é truee a expressão do operando do lado direito não é avaliada.
- Se o valor do operando do lado esquerdo for
false, a expressão do lado direito será avaliada; se o resultado tiver um tipo Boolean, ele estará sujeito à conversão de unboxing ( §5.1.8 ). O valor resultante se torna o valor da expressão condicional-ou.
- Assim,
||calcula o mesmo resultado que |on booleanou Booleanoperandos. Difere apenas no fato de a expressão do operando do lado direito ser avaliada condicionalmente, e não sempre.
Resumindo, como @JohnMeagher apontou repetidamente nos comentários, &e |são, de fato, operadores booleanos sem curto-circuito no caso específico dos operandos serem um booleanou outro Boolean. Com boas práticas (ou seja, sem efeitos secundários), essa é uma pequena diferença. Quando os operandos não são booleans ou Booleans, no entanto, os operadores se comportam de maneira muito diferente: as operações bit a bit e lógicas simplesmente não se comparam bem no alto nível da programação Java.