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 &&?

Foi útil?

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 para false
      • (Porque não importa o que o operando certo avalie, toda a expressão é false)
    • O operando esquerdo de || avalia para true
      • (Porque não importa o que o operando certo avalie, toda a expressão é true)

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 Predicates e faz avaliação de curto-circuito de ou/e Predicates.

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

Tutorial para operadores Java

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top