Utilidad de los operadores Bitwise como flags de indicadores en Java

Java

Muchos de vosotros habréis visto código similar a este:

Intent myIntent = new Intent(this, MyIntent.class)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION|Intent.FLAG_ACTIVITY_CLEAR_TOP);

Como ya lo sabréis este código es muy común en Android, pero también podemos encontrarnos con código similar en otros frameworks y plataformas.

El objetivo principal de este tipo de métodos y operaciones bitwise es la de poder indicar unas serie de flags que determina distintos comportamientos que puede tener el método.

Para poder conseguir esto vamos a utilizar algunos de los operadores bitwise.

Operadores bitwise

En java tenemos los siguientes operadores bitwise.

  • OR (|)
  • AND (&) y
  • XOR (^)

Como sabemos estos operadores son aplicados a nivel de bits, y su funcionamiento es el siguiente:

Bits            Operadores y Resultados
--------------- -----------------------
bit 1   bit 2   OR (|)  AND (&) XOR (^)
0       0       0       0       0
1       0       1       0       1
0       1       1       0       1
1       1       1       1       0

Utilización como indicadores de flags

Haciendo uso de estas operaciones bitwise podemos trabajar con indicadores de flags, donde cada bits puede representar, una operacion diferente a realizar.

Por ejemplo, podemos construir la siguiente secuencia de flags o indicadores utilizando el operador bitwise OR (|)

flags = 0000 | 0001 | 0100 = 0101

Y basandonos en la operacion bitwise AND (&) y en el operador de igualdad podemos preguntar por la existencia de uno de estos flags.

Si ((flags & flag_a_preguntar) == flags_a_preguntar)
    flag_a_preguntar SI encontrado
en caso contrario
    flag_a_preguntar NO encontrado

Por ejemplo, siendo flags igual a 0100 | 0001 = 0101

Si ((0101 & 0000 = 0101) == 0000), No encontrado
Si ((0101 & 0100 = 0100) == 0100), Encontrado
Si ((0101 & 1111 = 0101) == 1111), No encontrado

Para que esta funcionalidad puedan ser utilizada, debemos utilizar siempre un número decimal obtenido a partir de:

2 elevado a n, es decir:

2^0 = 1 decimal = 0000
2^1 = 2 decimal = 0010
2^2 = 4 decimal = 0100
2^3 = 8 decimal = 1000
2^4 = 16 decimal = 0001 0000
2^5 = 32 decimal = 0010 0000
etc

Si no, cuando realicemos las operaciones bitwise, obtendremos resultados errones.

Ejemplo Java WorkingWithBits

package es.example.bits;

public class WorkingWithBits {
    public static final int FLAG_1 = 1;
    public static final int FLAG_2 = 2;
    public static final int FLAG_3 = 4;
    public static final int FLAG_4 = 8;
    public static final int FLAG_5 = 16;
    public static final int FLAG_6 = 32;
    public static final int FLAG_7 = 64;
    public static final int FLAG_8 = 128;
    public static final int FLAG_9 = 256;
    public static final int FLAG_10 = 512;
    public static final int FLAG_11 = 1024;

    public static void main(String[] args) {
        int flags = FLAG_1|FLAG_3;
        isFlags(flags,"FLAG_1|FLAG_3");
        flags = FLAG_5|FLAG_1;
        isFlags(flags,"FLAG_5|FLAG_1");
        flags = FLAG_11|FLAG_3|FLAG_7;
        isFlags(flags,"FLAG_11|FLAG_3|FLAG_7");
        flags = FLAG_9|FLAG_11|FLAG_1|FLAG_7;
        isFlags(flags,"FLAG_9|FLAG_11|FLAG_1|FLAG_7");
    }

    public static void isFlags(int flags, String msg) {
        System.out.println("********************************");
        System.out.println("Flags recibidos: "+ msg);
        System.out.println("********************************");
        if ((flags & FLAG_1) == FLAG_1)
            System.out.println("FLAG_1 found");
        if ((flags & FLAG_2) == FLAG_2)
            System.out.println("FLAG_2 found");
        if ((flags & FLAG_3) == FLAG_3)
            System.out.println("FLAG_3 found");
        if ((flags & FLAG_4) == FLAG_4)
            System.out.println("FLAG_4 found");
        if ((flags & FLAG_5) == FLAG_5)
            System.out.println("FLAG_5 found");
        if ((flags & FLAG_6) == FLAG_6)
            System.out.println("FLAG_6 found");
        if ((flags & FLAG_7) == FLAG_7)
            System.out.println("FLAG_7 found");
        if ((flags & FLAG_8) == FLAG_8)
            System.out.println("FLAG_8 found");
        if ((flags & FLAG_9) == FLAG_9)
            System.out.println("FLAG_9 found");
        if ((flags & FLAG_10) == FLAG_10)
            System.out.println("FLAG_10 found");
        if ((flags & FLAG_11) == FLAG_11)
            System.out.println("FLAG_11 found");
    }
}

El resultado de su ejecución es el siguiente

*) Flags recibidos: FLAG_1|FLAG_3
FLAG_1 found
FLAG_3 found
*) Flags recibidos: FLAG_5|FLAG_1
FLAG_1 found
FLAG_5 found
*) Flags recibidos: FLAG_11|FLAG_3|FLAG_7
FLAG_3 found
FLAG_7 found
FLAG_11 found
*) Flags recibidos: FLAG_9|FLAG_11|FLAG_1|FLAG_7
FLAG_1 found
FLAG_7 found
FLAG_9 found
You can follow any responses to this entry through the RSS 2.0 feed.You can skip to the end and leave a response. Pinging is currently not allowed.

Leave a Reply

--------