¿Es una buena práctica utilizar el operador xor para verificaciones booleanas?


Personalmente me gusta la exclusiva o, ^, operador cuando tiene sentido en el contexto de comprobaciones booleanas debido a su concisión. Prefiero escribir

if (boolean1 ^ boolean2)
{
  //do it
}

Que

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
  //do it
}

Pero a menudo obtengo miradas confusas de otros desarrolladores de Java experimentados (no solo los novatos), y a veces comentarios sobre cómo solo se debe usar para operaciones bitwise.

Tengo curiosidad en cuanto a las mejores prácticas con respecto al uso del operador ^.

Author: nbro, 2008-10-02

13 answers

Simplemente puede usar != en su lugar.

 285
Author: vaxquis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-20 20:29:34

Creo que ha respondido a su propia pregunta: si obtiene miradas extrañas de la gente, probablemente sea más seguro optar por la opción más explícita.

Si necesitas comentarlo, entonces probablemente sea mejor reemplazarlo con la versión más detallada y no hacer que la gente haga la pregunta en primer lugar.

 27
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 03:34:54

Encuentro que tengo muchas conversaciones similares. Por un lado, tiene un método compacto y eficiente para lograr su objetivo. Por otro lado, usted tiene algo que el resto de su equipo puede no entender, por lo que es difícil de mantener en el futuro.

Mi regla general es preguntar si la técnica que se está utilizando es algo que es razonable esperar que los programadores en general sepan. En este caso, creo que es razonable esperar que los programadores sepan cómo usar operadores booleanos, por lo que usar xor en una sentencia if está bien.

Como ejemplo de algo que no estaría bien, tome el truco de usar xor para intercambiar dos variables sin usar una variable temporal. Ese es un truco con el que no esperaría que todos estuvieran familiarizados, por lo que no pasaría la revisión del código.

 16
Author: Dave Tarkowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 20:23:20

Creo que estaría bien si lo comentaras, por ejemplo, // ^ == XOR.

 14
Author: Dre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 20:18:38

Siempre puedes envolverlo en una función para darle un nombre detallado:

public static boolean XOR(boolean A, boolean B) {
    return A ^ B;
}

Pero, me parece que no sería difícil para cualquier persona que no sabía lo que el operador ^ es para Google realmente rápido. No va a ser difícil de recordar después de la primera vez. Ya que pediste otros usos, es común usar el XOR para enmascarar bits.

También puede usar XOR para intercambiar los valores en dos variables sin usar una tercera temporal variable .

// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;

Aquí hay una pregunta Stackoverflow relacionada con el intercambio XOR.

 8
Author: Cory Gross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-21 13:45:20

Recientemente usé un xor en un proyecto de JavaScript en el trabajo y terminé agregando 7 líneas de comentarios para explicar lo que estaba pasando. La justificación para usar xor en ese contexto fue que uno de los términos (term1 en el ejemplo siguiente) podría tomar no dos sino tres valores: undefined, true o false mientras que el otro (term2) podría ser true o false. Habría tenido que añadir una comprobación adicional para los undefined casos, pero con xor, lo siguiente era suficiente ya que el xor obliga a la primera término a ser evaluado primero como un booleano, dejando undefined ser tratado como false:

if (term1 ^ term2) { ...

Fue, al final, un poco exagerado, pero quería mantenerlo allí de todos modos, como una especie de huevo de pascua.

 6
Author: Ates Goral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 20:27:21

Con la claridad del código en mente, mi opinión es que el uso de XOR en comprobaciones booleanas no es un uso típico para el operador bitwise de XOR. Desde mi experiencia, bitwise XOR en Java es típicamente usado para implementar un comportamiento mask flag toggle:

flags = flags ^ MASK;

Este artículo de Vipan Singla explica el caso de uso con más detalle.

Si necesita usar XOR a BIT como en su ejemplo, comente por qué lo usa, ya que es probable que requiera incluso una audiencia alfabetizada a bit para detenerse en su pistas para entender por qué lo estás usando.

 5
Author: Gunnar Karlsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 20:21:19
if((boolean1 && !boolean2) || (boolean2 && !boolean1)) 
{ 
  //do it 
} 

EN mi humilde opinión este código podría simplificarse:

if(boolean1 != boolean2) 
{ 
  //do it 
} 
 4
Author: Y--,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-10 08:33:35

Si el patrón de uso lo justifica, ¿por qué no? Si bien su equipo no reconoce al operador de inmediato, con el tiempo podrían hacerlo. Los humanos aprenden nuevas palabras todo el tiempo. ¿Por qué no en programación?

La única advertencia que podría decir es que "^" no tiene la semántica de cortocircuito de su segunda comprobación booleana. Si realmente necesita la semántica de cortocircuito, entonces un método util estático también funciona.

public static boolean xor(boolean a, boolean b) {
    return (a && !b) || (b && !a);
}
 -1
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 03:08:30

Personalmente prefiero la expresión "boolean1 ^ boolean2" debido a su sucinta.

Si estuviera en su situación (trabajando en un equipo), llegaría a un compromiso encapsulando la lógica "boolean1 ^ boolean2" en una función con un nombre descriptivo como "isDifferent(boolean1, boolean2)".

Por ejemplo, en lugar de usar "boolean1 ^ boolean2", llamarías a "isDifferent (boolean1, boolean2)" de la siguiente manera:

if (isDifferent(boolean1, boolean2))
{
  //do it
}

Su función" isDifferent(boolean1, boolean2)" se vería así:

private boolean isDifferent(boolean1, boolean2)
{
    return boolean1 ^ boolean2;
}

Por supuesto, esta solución implica el uso de una llamada a una función aparentemente extraña, que en sí misma está sujeta al escrutinio de las Mejores Prácticas, pero evita la expresión verbosa (y fea) " (boolean1 && !boolean2) / / (boolean2 && !boolean1)"!

 -1
Author: ONE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-12 04:39:17

!= está bien comparar dos variables. Sin embargo, no funciona con comparaciones múltiples.

 -3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-05 10:13:25
str.contains("!=") ^ str.startsWith("not(")

Se ve mejor para mí que

str.contains("!=") != str.startsWith("not(")
 -3
Author: Chris Rea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-25 13:07:45

Como operador bit a bit, xor es mucho más rápido que cualquier otro medio para reemplazarlo. Por lo tanto, para cálculos críticos y escalables de rendimiento, xor es imperativo.

Mi opinión personal subjetiva: Está absolutamente prohibido, para cualquier propósito, utilizar la igualdad (==o!= ) para booleanos. Su uso muestra falta de ética y fundamentos básicos de programación. Cualquier persona que te da miradas confusas ^ debe ser enviado de nuevo a los fundamentos del álgebra booleana (tuve la tentación de escribir " a los ríos de creencia" aquí:)).

 -3
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-24 16:44:09