&& (AND) e || (OR) em instruções IF

Eu tenho o seguinte código:

if(!partialHits.get(req_nr).containsKey(z) || partialHits.get(req_nr).get(z) < tmpmap.get(z)){ partialHits.get(z).put(z, tmpmap.get(z)); } 

em que partialHits é um HashMap.
O que acontecerá se a primeira afirmação for verdadeira? O Java ainda verificará a segunda instrução? Porque, a fim de que a primeira instrução seja verdadeira, o HashMap não deve conter a chave dada, portanto, se a segunda instrução estiver marcada, receberei NullPointerException .
Então, em palavras simples, se tivermos o seguinte código

 if(a && b) if(a || b) 

O Java verificaria b se a é falso no primeiro caso e se a é verdadeiro no segundo caso?

Não, não será avaliado. E isso é muito útil. Por exemplo, se você precisa testar se uma String não é nula ou vazia, você pode escrever:

 if (str != null && !str.isEmpty()) { doSomethingWith(str.charAt(0)); } 

ou, o contrário

 if (str == null || str.isEmpty()) { complainAboutUnusableString(); } else { doSomethingWith(str.charAt(0)); } 

Se não tivéssemos ‘curtos-circuitos’ em Java, receberíamos muitas NullPointerExceptions nas linhas de código acima.

Java tem 5 diferentes operadores de comparação booleana: &, &&, |, ||, ^

& e && são “e” operadores, | e || “ou” operadores, ^ é “xor”

Os únicos irão verificar todos os parâmetros, independentemente dos valores, antes de verificar os valores dos parâmetros. Os duplos primeiro irão verificar o parâmetro esquerdo e seu valor e se true ( || ) ou false ( && ) deixar o segundo intocado. Som compilado? Um exemplo fácil deve deixar claro:

Dado para todos os exemplos:

  String aString = null; 

E:

  if (aString != null & aString.equals("lala")) 

Ambos os parâmetros são verificados antes que a avaliação seja feita e um NullPointerException será lançado para o segundo parâmetro.

  if (aString != null && aString.equals("lala")) 

O primeiro parâmetro é verificado e retorna false , então o segundo parâmetro não será verificado, porque o resultado é false qualquer maneira.

O mesmo para OR:

  if (aString == null | !aString.equals("lala")) 

Vai aumentar NullPointerException também.

  if (aString == null || !aString.equals("lala")) 

O primeiro parâmetro é verificado e retorna true , então o segundo parâmetro não será verificado, porque o resultado é true mesmo assim.

XOR não pode ser otimizado, porque depende dos dois parâmetros.

Não, não será verificado. Esse comportamento é chamado de avaliação de curto-circuito e é um recurso em vários idiomas, incluindo o Java.

Todas as respostas aqui são ótimas, mas, apenas para ilustrar de onde isso vem, para perguntas como esta, é bom ir à fonte: a Especificação da Linguagem Java.

Seção 15:23, operador Conditional-And (&&) , diz:

O operador && é como & (§15.22.2), mas avalia seu operando à direita somente se o valor do seu operando à esquerda for verdadeiro. […] Em tempo de execução, a expressão do operando à esquerda é avaliada primeiro […] se o valor resultante é falso, o valor da expressão condicional e é falso e a expressão do operando à direita não é avaliada . Se o valor do operando à esquerda for verdadeiro, a expressão à direita será avaliada […] e o valor resultante se tornará o valor da expressão condicional e. Assim, && calcula o mesmo resultado que & em operandos booleanos. Difere apenas porque a expressão do operando à direita é avaliada condicionalmente, e não sempre.

E da mesma forma, a Seção 15:24, operador Conditional-Or (||) , diz:

O || operador é como | (§15.22.2), mas avalia seu operando direito somente se o valor do seu operando esquerdo for falso. […] No tempo de execução, a expressão do operando à esquerda é avaliada primeiro; […] se o valor resultante for true, o valor da expressão condicional ou é verdadeiro e a expressão do operando à direita não é avaliada. Se o valor do operando à esquerda for falso, a expressão da mão direita será avaliada; […] o valor resultante se torna o valor da expressão condicional ou. Assim, || calcula o mesmo resultado que | em operandos booleanos ou booleanos. Difere apenas porque a expressão do operando à direita é avaliada condicionalmente, e não sempre.

Um pouco repetitivo, talvez, mas a melhor confirmação de como eles funcionam. Da mesma forma, o operador condicional (? 🙂 avalia apenas a ‘metade’ apropriada (metade esquerda se o valor for true, metade direita se for falsa), permitindo o uso de expressões como:

 int x = (y == null) ? 0 : y.getFoo(); 

sem um NullPointerException.

Não, se a for verdadeiro (em a or teste), b não será testado, pois o resultado do teste será sempre verdadeiro, qualquer que seja o valor da expressão b.

Faça um teste simples:

 if (true || ((String) null).equals("foobar")) { ... } 

não vai jogar um NullPointerException !

Não, não, o Java irá entrar em curto-circuito e parar de avaliar uma vez que saiba o resultado.

Sim, a avaliação de curto-circuito para expressões booleanas é o comportamento padrão em toda a família C-like.

Um fato interessante é que o Java também usa o & e | como operandos lógicos (eles estão sobrecarregados, com tipos int eles são as operações bit a bit esperadas) para avaliar todos os termos na expressão, o que também é útil quando você precisa dos efeitos colaterais.

Curto circuito aqui significa que a segunda condição não será avaliada.

Se (A && B) resultar em curto-circuito se A for Falso.

Se (A && B) não resultar em curto Circuito se A for Verdadeiro.

Se (A || B) resultará em curto-circuito se A for Verdadeiro.

Se (A || B) não resultará em curto-circuito se A for Falso.

Isso volta à diferença básica entre & e &&, | e ||

BTW você executa as mesmas tarefas muitas vezes. Não tenho certeza se a eficiência é um problema. Você poderia remover parte da duplicação.

 Z z2 = partialHits.get(req_nr).get(z); // assuming a value cannout be null. Z z3 = tmpmap.get(z); // assuming z3 cannot be null. if(z2 == null || z2 < z3){ partialHits.get(z).put(z, z3); }