Atalho “Or-Assignment” (| =) Operador em Java
-
21-09-2019 - |
Pergunta
Eu tenho um longo conjunto de comparações a fazer em Java, e gostaria de saber se um ou mais delas saírem como verdadeiras. A série de comparações era longa e difícil de ler, então eu a quebrei para a legibilidade e foi automaticamente usar um operador de atalho |=
ao invés de negativeValue = negativeValue || boolean
.
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
eu espero negativeValue
ser verdade se algum dos inadimplentesu003Csomething> Os valores são negativos. Isso é válido? Isso vai fazer o que eu espero? Eu não conseguia vê -lo mencionado no site da Sun ou Stackoverflow, mas o Eclipse não parece ter um problema com ele e o código compila e executa.
Da mesma forma, se eu quisesse realizar várias interseções lógicas, eu poderia usar &=
ao invés de &&
?
Solução
o |=
é um operador de atribuição composto (JLS 15.26.2) para o operador lógico booleano |
(JLS 15.22.2); não ser confundido com o condicional ou ||
(JLS 15.24). Há também &=
e ^=
correspondente à versão de atribuição composta do booleano lógico &
e ^
respectivamente.
Em outras palavras, para boolean b1, b2
, esses dois são equivalentes:
b1 |= b2;
b1 = b1 | b2;
A diferença entre os operadores lógicos (&
e |
) em comparação com seus colegas condicionais (&&
e ||
) é que o primeiro não "atalho"; o último faz. Aquilo é:
&
e|
sempre Avalie os dois operando&&
e||
Avalie o operando certo condicionalmente; O operando direito é avaliado apenas se seu valor puder afetar o resultado da operação binária. Isso significa que o operando certo não é avaliado quando:- O operando esquerdo de
&&
avalia parafalse
- (Porque não importa o que o operando certo avalie, toda a expressão é
false
)
- (Porque não importa o que o operando certo avalie, toda a expressão é
- O operando esquerdo de
||
avalia paratrue
- (Porque não importa o que o operando certo avalie, toda a expressão é
true
)
- (Porque não importa o que o operando certo avalie, toda a expressão é
- O operando esquerdo de
Então, voltando à sua pergunta original, sim, essa construção é válida e enquanto |=
não é exatamente um atalho equivalente para =
e ||
, ele calcula o que você deseja. Desde o lado direito do |=
O operador em seu uso é uma operação de comparação inteira simples, o fato de que |
não é insignificante.
Há casos, quando o atalho é desejado, ou mesmo necessário, mas seu cenário não é um deles.
É lamentável que, diferentemente de outras línguas, Java não tem &&=
e ||=
. Isso foi discutido na questão Por que o Java não possui versões de atribuição composta dos operadores condicionais e condicionais ou? (&& =, || =).
Outras dicas
Não é um operador de "atalho" (ou curto-circuito) da maneira que || e && estão (em que eles não avaliarão o RHS se já souberem o resultado com base no LHS), mas fará o que você deseja em termos de trabalhando.
Como exemplo da diferença, este código ficará bem se text
é nulo:
boolean nullOrEmpty = text == null || text.equals("")
Considerando que isso não vai:
boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null
(Obviamente você poderia fazer "".equals(text)
Para esse caso em particular - estou apenas tentando demonstrar o princípio.)
Você poderia apenas ter uma declaração. Expressado por várias linhas, ele lê quase exatamente como o seu código de exemplo, apenas menos imperativo:
boolean negativeValue
= defaultStock < 0
| defaultWholesale < 0
| defaultRetail < 0
| defaultDelivery < 0;
Para expressões mais simples, usando |
pode ser mais rápido que ||
Porque, embora evite fazer uma comparação, isso significa usar um ramo implicitamente e isso pode ser muitas vezes mais caro.
Embora possa ser um exagero para o seu problema, o Goiaba A biblioteca tem uma boa sintaxe com Predicate
s e faz avaliação de curto-circuito de ou/e Predicate
s.
Essencialmente, as comparações são transformadas em objetos, embaladas em uma coleção e depois iteradas. Para ou predicados, o primeiro verdadeiro sucesso retorna da iteração e vice -versa para e.
Se se trata de legibilidade, tenho o conceito de separação testada dados da lógica de teste. Exemplo de código:
// declare data
DataType [] dataToTest = new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
}
// define logic
boolean checkIfAnyNegative(DataType [] data) {
boolean negativeValue = false;
int i = 0;
while (!negativeValue && i < data.length) {
negativeValue = data[i++] < 0;
}
return negativeValue;
}
O código parece mais detalhado e auto-explicativo. Você pode até criar uma matriz na chamada de método, assim:
checkIfAnyNegative(new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
});
É mais legível que 'String de comparação' e também possui vantagem de desempenho de curto-circuito (ao custo da alocação de matrizes e da chamada de método).
Editar:Ainda mais legibilidade pode ser simplesmente alcançado usando parâmetros VARARGS:
A assinatura do método seria:
boolean checkIfAnyNegative(DataType ... data)
E a chamada pode ficar assim:
checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );
É um post antigo, mas para fornecer uma perspectiva diferente para iniciantes, gostaria de dar um exemplo.
Eu acho que o caso de uso mais comum para um operador de composto semelhante seria +=
. Tenho certeza de que todos escrevemos algo assim:
int a = 10; // a = 10
a += 5; // a = 15
Qual foi o objetivo disto? O objetivo era evitar o Boilerplate e eliminar o código repetitivo.
Portanto, a próxima linha faz exatamente o mesmo, evitando digitar a variável b1
duas vezes na mesma linha.
b1 |= b2;
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale,
defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
|| booleano lógico ou
| Bit nejudado ou
| = Operador de atribuição inclusivo ou bit
A razão pela qual | = não é o shortcircit é porque ele faz um bit bit ou não um lógico ou. Isto é, dizer:
C |= 2 is same as C = C | 2