&& (E) e | | / (ou) em declarações IF

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));  
}

onde partialHits é um HashMap.
O que acontecerá se a primeira afirmação for verdadeira? Java ainda vai verificar a segunda declaração? Porque para que a primeira declaração seja verdadeira, a HashMap não deve conter a chave indicada, por isso, se a segunda declaração for verificada, eu vou obter NullPointerException.
Então, em palavras simples, se tivermos o seguinte código

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

o Java check b se a for falso no primeiro caso e se a for verdade no segundo caso?

Author: Amr, 2009-11-25

9 answers

Não, Não será avaliado. E isto é muito útil. Por exemplo, se você precisar testar se uma String não é nula ou vazia, você pode escrever:
if (str != null && !str.isEmpty()) {
  doSomethingWith(str.charAt(0));
}

Ou ao contrário

if (str == null || str.isEmpty()) {
  complainAboutUnusableString();
} else {
  doSomethingWith(str.charAt(0));
}
Se não tivéssemos "short-circuits" em Java, receberíamos muitas dicas de pontos nulos nas linhas de código acima.
 172
Author: Andreas_D, 2018-03-15 00:39:20

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 Irão primeiro verificar o parâmetro esquerdo e seu valor e se true (||) ou false (&&) deixa o segundo intocado. Som compilado? Um exemplo fácil deve fazê-lo limpo:

dados para todos os exemplos:

 String aString = null;

E:

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

Ambos os parâmetros são verificados antes da Avaliação ser feita e será lançada uma derrogação NULL para o segundo parâmetro.

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

O primeiro parâmetro está assinalado e devolve false, por isso o segundo parâmetro não será verificado, porque o resultado é false de qualquer forma.

O mesmo para ou:

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

Também vai aumentar a percepção de ponto final.

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

O primeiro o parâmetro está assinalado e devolve true, por isso o segundo parâmetro não será assinalado, porque o resultado é true de qualquer forma.

O XOR não pode ser optimizado, porque depende de ambos os parâmetros.

 58
Author: Hardcoded, 2013-05-15 07:46:11
Não, Não será verificado. Este comportamento é chamado de avaliação de curto-circuito e é uma característica em muitas linguagens, incluindo Java.
 27
Author: Peter van der Heijden, 2009-11-25 10:04:21

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

Secção 15: 23, condicional-e operador (&&), diz:

O & operador é como &(§15.22.2), mas avalia o seu operando à direita apenas se o valor do seu operando à esquerda for verdadeiro. [...] At run time, the left-hand operand expression is evaluated first [...] se o valor resultante is false, the value of the conditional-and expression is false and the right-hand operand expression is not evaluated. Se o valor do operando da esquerda é verdadeiro, então a expressão da direita é avaliada [...] o valor resultante torna-se o valor do condicional-e expressão. Thus, & & computes the same result as & on boolean operands. Ela difere apenas porque a expressão de operação à direita é avaliada condicionalmente e não sempre.

E da mesma forma, Secção 15: 24, condicional-ou operador (||), diz:

O / / operador é igual a | (§15.22.2), mas avalia o seu comando direito apenas se o valor do seu comando esquerdo for falso. [...] At run time, the left-hand operand expression is evaluated first; [...] se o valor resultante for verdadeiro, o valor do condicional-ou expressão é verdadeiro e a expressão do operando à direita não é avaliada. Se o valor do operando da esquerda for falso, então o da direita a expressão é avaliada; [...] o valor resultante torna-se o valor do condicional-ou expressão. Assim | / / calcula o mesmo resultado que | em operandos booleanos ou booleanos. Ela difere apenas porque a expressão de operação à direita é avaliada condicionalmente e não sempre.

Um pouco repetitivo, talvez, mas a melhor confirmação de como funcionam. Da mesma forma, o operador condicional (?:) só avalia a "metade" apropriada (metade esquerda se o valor for verdadeiro, metade direita se for falso), permitindo o uso de expressões como:
int x = (y == null) ? 0 : y.getFoo();

Sem um ponto final.

 19
Author: Cowan, 2009-11-25 10:15:50

Não, se a for verdadeiro( num teste or, b não será testado, pois o resultado do teste será sempre verdadeiro, seja qual for o valor da expressão B.

Faça um teste simples:

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

Willnot throw a NullPointerException!

 5
Author: romaintaz, 2009-11-25 09:53:18
Não vai, Java vai fazer curto-circuito e parar de avaliar quando souber o resultado.
 4
Author: abyx, 2009-11-25 09:53:42

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

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

 4
Author: fortran, 2009-11-27 11:30:04
Curto-circuito significa que a segunda condição não será avaliada.

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

Se ( a & B ) for not result in short Circuit if A is True.

Se ( a / / B ) resultar em curto-circuito se A for verdadeiro.

Se ( A || B ) will not result in short circuit if A is False.

 4
Author: user3211238, 2014-06-13 15:02:49

Isto remonta à diferença básica entre & e & & | / e / /

BTW você executa as mesmas tarefas muitas vezes. Não sei se a eficiência é um problema. Pode remover alguma 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);   
} 
 0
Author: Peter Lawrey, 2010-05-11 20:16:34