Operadores lógicos
Se você estudou ciência da computação, talvez já tenha se deparado com operadores lógicos. Caso contrário, não há necessidade de entrar em pânico. Vamos abordá-los detalhadamente nesta seção.
Os operadores lógicos, (&), (|) e (^), podem ser aplicados a tipos de dados numéricos e booleanos. Quando eles são aplicados a tipos de dados booleanos, eles são chamados de operadores lógicos. Como alternativa, quando eles são aplicados a tipos de dados numéricos, eles são chamados de operadores bit a bit, pois realizam comparações bit a bit dos bits que compõem o número. No entanto, para o exame, você não precisa saber nada sobre as comparações numéricas de bit a bit, por isso vamos deixar esse aspecto educacional para outros livros.
Você deve se familiarizar com as tabelas da verdade na Figura 2.1, onde x e y são considerados tipos de dados booleanos.
Aqui estão algumas dicas para ajudar a lembrar esta tabela:
■ AND só é verdadeiro se os dois operandos forem verdadeiros.
■ OR inclusivo só é falso se ambos os operandos forem falsos.
■ OR exclusivo só é verdadeiro se os operandos forem diferentes.
Finalmente, apresentamos os operadores condicionais, && e ||, que são freqüentemente chamados de operadores de curto-circuito. Os operadores de curto-circuito são parecidos com os operadores lógicos, & e |, respectivamente, exceto que o lado direito da expressão não puder ser avaliado porque o resultado final for determinado pelo lado esquerdo da expressão. Por exemplo, considere a seguinte declaração:
boolean x = true || (y < 4);
Referindo-se às tabelas de verdade, o valor x só pode ser falso se ambos os lados da expressão forem falsos. Como sabemos que o lado esquerdo é verdadeiro, não há necessidade de avaliar o lado direito, pois nenhum valor de y fará com que o valor de x seja diferente de verdadeiro. Isso pode ajudá-lo a ilustrar esse conceito executando a linha de código anterior para vários valores de y.
Um exemplo mais comum de onde os operadores de curto-circuito são usados é a verificação de objetos nulos antes de executar uma operação, como esta:
if(x != null && x.getValue() < 5) {
// Do something
}
Neste exemplo, se x for nulo, o curto-circuito impede que uma NullPointerException seja lançada, pois a avaliação de x.getValue() <5 nunca é atingida. Alternativamente, se usássemos um & lógico, então ambos os lados sempre seriam avaliados e quando x fosse nulo isto lançaria uma exceção:
if(x != null & x.getValue() < 5) { // Throws an exception if x is null
// Do something
}
Desconfie de um comportamento de curto-circuito no exame, pois sabe-se que as perguntas alteram uma variável no lado direito da expressão que talvez nunca seja alcançada. Por exemplo, qual é a saída do código a seguir?
int x = 6;
boolean y = (x >= 6) || (++x <= 7);
System.out.println(x);
Como x >= 6 é verdadeiro, o operador de incremento no lado direito da expressão nunca é avaliado, portanto, a saída é 6.