Primeiro, alguns antecedentes: sou professor de treinamento em TI e estou tentando introduzir os operadores booleanos de java na minha turma da 10ª série. Meu professor-mentor examinou uma planilha que eu preparei e comentei que poderia deixá-los usar apenas uma única & ou | denotar os operadores, porque "fazem a mesma coisa".
Estou ciente da diferença entre & e &&.
& é um operador bit a bit destinado ao uso entre números inteiros, para executar "ajustes de bits".
&& é um operador condicional destinado ao uso entre valores booleanos.
Para provar que esses operadores nem sempre "fazem a mesma coisa", propus-me a encontrar um exemplo em que o uso do bit a bit entre valores booleanos levaria a um erro. Eu encontrei este exemplo
boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10;
conditional = (i<j) || (i=3) > 5 ; // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10;
bitwise = (i>j) & (i=3) > 5; // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10;
conditional = (i>j) && (i=3) > 5; // value of i after oper: 10
System.out.println(conditional+ " "+ i);
Este exemplo mostra que, se um valor tiver que ser alterado na segunda metade da expressão, isso levaria a uma diferença entre os resultados, já que o bit a bit é um operador ansioso, enquanto o condicional se comporta como um curto-circuito (não avalia o segundo metade, se a primeira metade for falsa no caso de && e verdadeira no caso de ||).
Eu tenho um problema com este exemplo. Por que você deseja alterar um valor ao mesmo tempo em que faz uma comparação? Não parece uma maneira robusta de codificar. Eu sempre fui avesso a fazer várias operações em uma única linha no meu código de produção. Parece algo que um "cowboy de codificação" sem consciência quanto à manutenção de seu código faria. Eu sei que em alguns domínios o código precisa ser o mais compacto possível, mas certamente essa é uma prática ruim em geral?
Eu posso explicar minha escolha de incentivar o uso de && e || sobre & e | porque esta é uma convenção de codificação aceita em engenharia de software .
Mas alguém poderia me dar um exemplo melhor, até do mundo real, do uso de um operador bit a bit em uma expressão condicional?
fonte
bitwise = !(true & true == false);
econdition = !(true && true == false);
ambos irão avaliar a verdade, portanto, neste caso, eles são intercambiáveis? Sintaticamente, talvez, já que o código ainda é compilado. Concordo que eles são usados para coisas diferentes semanticamente, como mencionei no parágrafo 2. Você diz isso! e & "quase nunca aparecem condicionais por si mesmos". Estou procurando esses casos "quase nunca" e me perguntando se eles existem legitimamente.Os operadores não bit a bit
&&
e||
são operadores de curto-circuito. Em outras palavras, com&&
, se o LHS for falso, o RHS nunca será avaliado; com||
se o LHS for verdadeiro, o RHS nunca será avaliado. Por outro lado, os operadores bit a bit&
e|
são sem curto-circuito e sempre avaliarão o LHS e o RHS. Caso contrário, eles são equivalentes em umif
declaração.A única vez em que vejo valor ao usar operadores sem curto-circuito é se o RHS tiver algum tipo de efeito colateral desejável que você deseja que aconteça em todos os casos. Não consigo pensar em um exemplo específico em que você queira isso e não acredito que seja uma boa prática, mas essa é a diferença.
fonte
A resposta filosófica geral é que o uso de operadores bit a bit para operadores booleanos é atípico e dificulta a leitura do código. Na prática (para código em produção), um código mais legível é mais fácil de manter e, portanto, mais desejável.
Para uma utilização real da necessidade de operadores de curto-circuito, consulte casos como:
Esse tipo de operação aparece frequentemente no código do mundo real.
fonte
&
é "mais difícil de ler" que 2? Não tenho um exemplo no qual os 2 operadores não funcionem da mesma maneira para operandos booleanos. Concordo com seu ponto de vista sobre um código mais legível e mais fácil de manter. Quero encorajá-los a escrever um código bonito. Mas ter alguma prova na minha bolsa de ferramentas seria mais convincente do que "porque eu disse isso". Eu tenho isso declarado como padrão nesse link, e pode ter que confiar apenas nisso, se eu não conseguir o exemplo que estou procurando. Como perguntei a Steve Haigh: o java deveria indicar isso como um uso inadequado?Você usará operadores bit a bit se comparar as enumerações de Bitmask. Por exemplo, você tem uma enumeração de estados e um objeto que pode estar em mais de um desses estados. Nesse caso, você fará um bit a bit ou para atribuir mais de um estado ao seu objeto.
por exemplo,
state = CONNECTED | IN_PROGRESS
ondeCONNECTED could be 0x00000001
eIN_PROGRESS 0x00000010
Para obter mais informações, consulte a documentação de enumerações de sinalizadores.
fonte
um exemplo mais simples de erro:
aqui você tem duas condições, ambas são diferentes de zero; mas o bit a bit
&
resulta em zero.fonte
(condA && condB)
erros, porque o && não funciona por 2int
s, apenas 2 booleanos.(condA & condB)
enquanto correto, avalia para umint
e em java, não podemos dizerif(int)
que também erros. Você é o primeiro a entender o que estou procurando - exatamente esse exemplo de erro .(Boolean(condA) && Boolean(condB))
(eu acho queBoolean(x)
étrue
para não-zero de números inteiros, né?)((condA!=0) && (condB!=0))
?if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }
executa ambas as instruções de impressão.