Tenho um longo conjunto de comparações para fazer em Java e gostaria de saber se uma ou mais delas são verdadeiras. A sequência de comparações era longa e difícil de ler, então eu a separei para facilitar a leitura e automaticamente passei a usar um operador de atalho em |=
vez de negativeValue = negativeValue || boolean
.
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
Espero negativeValue
que seja verdade se algum dos valores padrão de <algo> for negativo. Isso é válido? Vai fazer o que eu espero? Eu não pude ver isso mencionado no site da Sun ou stackoverflow, mas o Eclipse não parece ter problemas com isso e o código compila e executa.
Da mesma forma, se eu quisesse realizar várias interseções lógicas, poderia usar em &=
vez de &&
?
java
assignment-operator
compound-assignment
or-operator
David Mason
fonte
fonte
||=
operador não existente , mas|=
é a forma de combinação do operador bit a bit ou.|=
curto-circuito seria inconsistente com outros operadores de atribuição compostos, uma veza |= b;
que não seria o mesmo quea = a | b;
, com a advertência usual sobre avaliara
duas vezes (se for importante). Parece-me que a grande decisão sobre o comportamento da linguagem não estava ocorrendo||=
, então não estou entendendo.Respostas:
O
|=
é um operador de atribuição composto ( JLS 15.26.2 ) para o operador lógico booleano|
( JLS 15.22.2 ); não deve ser confundido com o condicional ou||
( JLS 15.24 ). Existem também&=
e^=
correspondentes à versão de atribuição composta da lógica booleana&
e^
respectivamente.Em outras palavras, para
boolean b1, b2
, esses dois são equivalentes:A diferença entre os operadores lógicos (
&
e|
) em comparação com suas contrapartes condicionais (&&
e||
) é que os primeiros não "curto-circuito"; o último faz. Isso é:&
e|
sempre avaliar ambos os operandos&&
e||
avaliar o operando certo condicionalmente ; o operando certo é avaliado apenas se seu valor puder afetar o resultado da operação binária. Isso significa que o operando certo NÃO é avaliado quando:&&
avalia parafalse
false
)||
avalia paratrue
true
)Então, voltando à sua pergunta original, sim, essa construção é válida, e while
|=
não é exatamente um atalho equivalente para=
e||
, ele calcula o que você deseja. Como o lado direito do|=
operador em seu uso é uma operação simples de comparação de inteiros, o fato de|
não causar curto-circuito é insignificante.Há casos em que o curto-circuito é desejado, ou mesmo obrigatório, mas o seu cenário não é um deles.
É uma pena que, ao contrário de outras linguagens, Java não tenha
&&=
e||=
. Isso foi discutido na pergunta Por que o Java não tem versões de atribuição composta dos operadores condicional e e condicional ou? (&& =, || =) .fonte
|
Não é um operador de "atalho" (ou curto-circuito) da maneira que || e && são (no sentido de que eles não avaliarão o RHS se já souberem o resultado baseado no LHS), mas fará o que você quiser em termos de trabalho .
Como um exemplo da diferença, este código ficará bem se
text
for nulo:enquanto isso não:
(Obviamente, você poderia servir
"".equals(text)
nesse caso específico - estou apenas tentando demonstrar o princípio.)fonte
Você poderia ter apenas uma declaração. Expresso em várias linhas, ele é lido quase exatamente como seu código de amostra, mas menos imperativo:
Para expressões mais simples, usar
|
pode ser mais rápido do que||
porque, embora evite fazer uma comparação, significa usar uma ramificação implicitamente e isso pode ser muito mais caro.fonte
Embora possa ser um exagero para o seu problema, a biblioteca Guava tem uma boa sintaxe com se
Predicate
faz avaliação de curto-circuito de or / ePredicate
s.Essencialmente, as comparações são transformadas em objetos, empacotadas em uma coleção e, em seguida, iteradas. Para ou predicados, o primeiro hit verdadeiro retorna da iteração e vice-versa para e.
fonte
Se for sobre legibilidade, tenho o conceito de separação de dados testados da lógica de teste. Amostra de código:
O código parece mais detalhado e autoexplicativo. Você pode até criar uma matriz na chamada de método, assim:
É mais legível do que 'string de comparação' e também tem a vantagem de desempenho de curto-circuito (ao custo de alocação de array e chamada de método).
Editar: ainda mais legibilidade pode ser alcançada simplesmente usando parâmetros varargs:
A assinatura do método seria:
E a chamada pode ser assim:
fonte
É um post antigo, mas para dar uma perspectiva diferente para iniciantes, gostaria de dar um exemplo.
Acho que o caso de uso mais comum para um operador composto semelhante seria
+=
. Tenho certeza de que todos nós escrevemos algo assim:Qual foi o objetivo disto? O objetivo era evitar boilerplate e eliminar o código repetitivo.
Assim, a próxima linha faz exatamente o mesmo, evitando digitar a variável
b1
duas vezes na mesma linha.fonte
longNameOfAccumulatorAVariable += 5;
vs.longNameOfAccumulatorAVariable = longNameOfAccumulatorVVariable + 5;
fonte
negativeValue = defaultStock < 0 || defaultWholesale < 0
etc. Além da ineficiência de todo o encaixotamento e embalagem acontecendo aqui, não acho tão fácil entender o que seu código realmente significaria.|| OR booleano lógico
| bit a bit OU
| = bit a bit OR inclusivo e operador de atribuição
A razão pela qual | = não curto-circuito é porque ele faz um OR bit a bit e não um OR lógico. Quer dizer:
Tutorial para operadores java
fonte
|
é um número inteiro OR bit a bit, mas também é OR lógico - consulte a Especificação de linguagem Java 15.22.2.