¿Cuáles son los casos en los que es mejor usar AND incondicional (y en lugar de &&)?

Me gustaría conocer algunos casos en Java (o más en general: en progtwigción) cuando se prefiere en expresiones booleanas usar AND ( & ) incondicional en lugar de la versión condicional ( && ).

Sé cómo funcionan, pero no puedo pensar en un caso cuando uso el single & lo vale.

He encontrado casos en la vida real donde ambos lados de la expresión eran realmente baratos, por lo que se redujo un nanosegundo o dos para evitar la twig y usar el incondicional & lugar de && . (Éstas fueron utilidades de matemática de muy alto rendimiento, casi nunca usaría esto en otro código, y no lo hubiera hecho de todos modos sin una evaluación comparativa exhaustiva para demostrar que era mejor).

(Para dar ejemplos específicos, x > 0 va a ser súper barato y sin efectos secundarios. ¿Por qué molestarse en arriesgar una predicción errónea de una twig para evitar una prueba que va a ser tan barata de todos modos? Claro, dado que es un boolean el resultado final es va a ser utilizado en una twig de todos modos, pero if (x >= 0 && x <= 10) implica dos twigs, y if (x >= 0 & x <= 10) implica solo una.

La única diferencia es que && y || detener la evaluación tan pronto como se sepa. Así por ejemplo:

 if (a != null && a.get() != null) 

funciona bien con && , pero con & podrías obtener una NullPointerException si a es nulo.

El único caso en el que puedo pensar dónde quieres usar es si el segundo operando tiene un efecto secundario, por ejemplo (probablemente no sea el mejor ejemplo pero entiendes el punto):

 public static void main(String[] args) { int i = 1; if (i == 0 & ++i != 2) { } System.out.println(i); //2 i = 1; if (i == 0 && ++i != 2) { } System.out.println(i); //1 } 

Sin embargo, esto me parece un código maloliente (en ambos casos).

El && permite al jvm hacer una evaluación de cortocircuito. Es decir, si el primer argumento es falso, entonces no necesita molestarse en verificar el segundo argumento.

Un single y ejecutará ambos lados independientemente.

Entonces, como un ejemplo artificial, podrías tener:

 if (account.isAllowed() & logAccountAndCheckFlag(account)) // Do something 

En ese ejemplo, es posible que siempre desee registrar el hecho de que el propietario de la cuenta intentó hacer algo.

No obstante, creo que nunca he usado una sola y en la progtwigción comercial.

Wikipedia ha descrito muy bien la evaluación de corto circuito

¿Dónde prefieres operadores sin cortocircuito?

Desde el mismo enlace:

  • La segunda condición no comprobada conduce a un efecto secundario no realizado
  • Eficiencia del código

El cortocircuito puede provocar errores en la predicción de bifurcación en los procesadores modernos y reducir drásticamente el rendimiento (un ejemplo notable es un rayo altamente optimizado con un código de intersección de caja alineado con el eje en el trazado de rayos) [se necesita aclaración]. Algunos comstackdores pueden detectar dichos casos y emitir códigos más rápidos, pero no siempre es posible debido a posibles violaciones del estándar C. El código altamente optimizado debe usar otras formas para hacer esto (como el uso manual del código de ensamblaje)

Si hay efectos secundarios que deben suceder, pero eso es un poco feo.

El AND a nivel de bit ( & ) es principalmente útil para eso: matemática bit a bit.

La validación de entrada es un posible caso. Por lo general, desea informar todos los errores en un formulario al usuario en un solo paso en lugar de detenerse después del primero y forzarlos a hacer clic en enviar repetidamente y obtener un solo error cada vez:

 public boolean validateField(string userInput, string paramName) { bool valid; //do validation if (valid) { //updates UI to remove error indicator (if present) reportValid(paramName); } else { //updates UI to indicate a problem (color change, error icon, etc) reportInvalid(paramName); } } public boolean validateAllInput(...) { boolean valid = true; valid = valid & validateField(userInput1, paramName1); valid = valid & validateField(userInput2, paramName2); valid = valid & validateField(userInput3, paramName3); valid = valid & validateField(userInput4, paramName4); valid = valid & validateField(userInput5, paramName5); return valid; } public void onSubmit() { if (validateAllInput(...)) { //go to next page of wizard, update database, etc processUserInput(userInput1, userInput2, ... ); } } public void onInput1Changed() { validateField(input1.Text, paramName1); } public void onInput2Changed() { validateField(input2.Text, paramName2); } ... 

De acuerdo, podría evitar trivialmente la necesidad de una evaluación de cortocircuito en validateAllInput() refactorizando la lógica if (valid) { reportValid() ... fuera de validateField() ; pero luego necesitarás llamar al código extraído cada vez que se invoque validateField (); como mínimo, agregar 10 líneas adicionales para las llamadas a métodos. Como siempre, es un caso de intercambio que funciona mejor para usted.

Si la expresión es trivial, puede obtener una microoptimización usando & o | en eso estás previniendo una twig. es decir.

 if(a && b) { } if(!(a || b)) { } 

es lo mismo que

 if (a) if (b) { } if (!a) if (!b) { } 

que tiene dos lugares puede ocurrir una bifurcación.

Sin embargo, usando un signo incondicional o | , solo puede haber una twig

Siempre que esto ayude o no depende en gran medida de lo que el código está haciendo.

Si usa esto, sugiero comentarlo para dejar muy claro por qué se ha hecho.

No hay ningún uso específico de solo, pero puedes considerar la siguiente situación.

 if (x > 0 & someMethod(...)) { // code... } 

Considere que someMethod() está haciendo alguna operación que modificará variables de instancia o hará algo que afectará el comportamiento más adelante en el procesamiento.

Entonces, en este caso, si usas && operador y la primera condición falla, nunca irá en someMethod() . En este caso, solo & operador será suficiente.

Como & es un operador poco inteligente, puede hacer hasta 32 comprobaciones en una sola operación al mismo tiempo. Esto puede convertirse en una ganancia de velocidad significativa para estos casos de uso muy específicos. Si necesita verificar una gran cantidad de condiciones, hágalo a menudo y el costo de boxeo / desembalaje de las condiciones se amortiza por el número de cheques, o si almacena sus datos en disco y en RAM en ese formato ( es más eficiente desde el punto de vista del espacio para almacenar 32 condiciones en una sola máscara de bits), el operador & puede dar un gran beneficio de velocidad en una serie de 32 individuos && . Por ejemplo, si desea seleccionar todas las unidades que se pueden mover, es una infantería, tiene una mejora de arma y está controlada por el jugador 3, puede hacer:

 int MASK = CAN_MOVE | INFANTRY | CAN_ATTACK | HAS_WEAPON_UPGRADE | PLAYER_3; for (Unit u in allunits) { if (u.mask & MASK == MASK) { ...; } } 

Vea mis otras respuestas en una pregunta relacionada para obtener más información sobre el tema.

El único beneficio que se me ocurre es cuando necesita invocar un método o ejecutar un código, sin importar que la primera expresión se evalúe como true o false :

 public boolean update() { // do whatever you want here return true; } // ... if(x == y & update()){ /* ... */} 

Aunque puedes hacer esto sin & :

 if(x == y){/* ... */} update(); 

El cortocircuito puede provocar errores en la predicción de bifurcación en los procesadores modernos y reducir drásticamente el rendimiento (un ejemplo notable es un rayo altamente optimizado con un código de intersección de caja alineado con el eje en el trazado de rayos) [se necesita aclaración].