&& (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?
9 answers
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.
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.
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:
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: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.
int x = (y == null) ? 0 : y.getFoo();
Sem um ponto final.
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
!
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.
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.
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);
}