Operador XOR en Java

Comencemos recordando la semántica de la operación XOR. La operación lógica XOR, o exclusiva, toma dos operandos booleanos y devuelve verdadero si, y solo si, los operandos son diferentes. Por el contrario, devuelve falso si los dos operandos tienen el mismo valor.

Por ejemplo, el operador XOR se puede utilizar cuando tenemos que comprobar si hay dos condiciones que no pueden ser verdaderas al mismo tiempo.

Consideremos dos condiciones, A y B. La siguiente tabla muestra los posibles valores de A XOR B:

ABA XOR B
truetruefalse
truefalsetrue
falsetruetrue
falsefalsefalse

La operación A XOR B es equivalente a (A AND !B) OR (!A AND B). Se han incluido paréntesis para mayor claridad, pero son opcionales, ya que el operador AND tiene prioridad sobre el operador OR.

¿Cómo hacerlo en Java?

Ahora veamos cómo expresar la operación XOR en Java. Por supuesto, tenemos la opción de usar los operadores && y ||, pero esto puede ser un poco complejo, como veremos.

Imaginemos una clase Car que tiene dos atributos booleanos: diesel y manual. Ahora digamos que queremos saber si el auto es diesel o manual, pero no ambos.

Comprobémoslo usando los operadores && y ||:

CuentaBancaria cuenta = CuentaBancaria.cuentaConSaldoYActiva();
boolean saldoXorActiva = (cuenta.tieneSaldo() && !cuenta.estaActiva()) || (!cuenta.tieneSaldo() && cuenta.estaActiva());

Eso es un poco largo, especialmente si tenemos en cuenta que tenemos una alternativa, el operador XOR de Java representado por el símbolo ^. Es un operador bit a bit, lo que significa que es un operador que compara los bits coincidentes de dos valores para devolver un resultado. En el caso de XOR, si dos bits de la misma posición tienen el mismo valor, el bit resultante será 0. De lo contrario, será 1.

Entonces, en lugar de nuestra engorrosa implementación XOR, podemos usar el operador ^ directamente:

CuentaBancaria cuenta = CuentaBancaria.cuentaConSaldoYActiva();
boolean saldoXorActiva = cuenta.tieneSaldo() ^ cuenta.estaActiva();

Como podemos ver, el operador ^ nos permite ser más concisos a la hora de expresar operaciones XOR.

Por último, cabe mencionar que el operador XOR, al igual que los demás operadores bit a bit, funciona con todos los tipos primitivos. Por ejemplo, consideremos dos números enteros, 1 y 3, cuyas representaciones binarias son 00000001 y 000000011, respectivamente. Al utilizar el operador XOR entre ellos, obtendremos el número entero 2:

assertThat(1 ^ 3).isEqualTo(2);

Sólo el segundo bit es diferente en esos dos números; por lo tanto, el resultado del operador XOR en este bit será 1. Todos los demás bits son idénticos, por lo que su resultado XOR bit a bit es 0, lo que nos da un valor final de 00000010, la representación binaria del entero 2.