首先通过定义一组静态常量来定义多个状态:1
2
3
4public static final int OP_READ = 1<<0;
public static final int OP_WRITE = 1<<2;
public static final int OP_CONNECT = 1<<3;
public static final int OP_ACCEPT = 1<<4;
如果把它们转换为二进制:1
2
3
41<<0: 0000 0001
1<<2: 0000 0100
1<<3: 0000 1000
1<<4: 0001 0000
可以发现,一个数如果是 2 的幂,则它的二进制数都只有一个位为 1,其余位数都是 0.
存储状态
下面再来定义一个变量,用来存储状态(默认值是 0):1
private static int STATUS = 0;
当需要保存状态时,直接用按位或运算 | :1
2//假如需要保存状态 OP_READ
STATUS = STATUS | OP_READ;
保存的运算过程如下:1
2
3
4
50000 0000
执行 | 运算
0000 0001
---------
0000 0001
相当于把 1 这个状态值存储到 0 的二进制当中。
可以在
STATUS
中存储多个状态值,STATUS = OP_READ | OP_WRITE | OP_CONNECT
判断状态
那么如果要判断变量 STATUS
中是否有某个状态呢?这时候需要使用 & 运算:1
( STATUS & OP_READ ) != 0 //true,代表含有 OP_READ
计算过程如下:1
2
3
4
50000 0001
执行 & 运算
0000 0001
---------
0000 0001
再来判断一个不存在的状态 STATUS & OP_WRITE
:1
( STATUS & OP_WRITE ) != 0; //false,代表不含有 OP_WRITE
计算过程如下:1
2
3
4
50000 0001
执行 & 运算
0000 0010
----------
0000 0000 = 0
因为 OP_WRITE
这个状态的二进制位,1 的位置处,STATUS
的二进制并没有对应的 1,而又因为其他位都是 0,导致全部归 0,计算出来的结果自然也就是 0 了。
这也就是为什么定义状态的数字中,都是 2 的次幂,因为它们的特点就是二进制只有一个为 1 的位,其他位都是 0,并同其他数位 1 的位不冲突。
移除已存储状态
现在知道了如何存储和判断状态,那么如何移除已经存储的状态呢?这时候就要用到非运算 ^ 。
假设 STATUS
中已经存储了 OP_CONNECT
这个状态,要把它从 STATUS
中移除,可以写:1
STATUS = STATUS ^ OP_CONNECT
计算过程:1
2
3
4
50000 1000
执行 ^ 运算
0000 1000
---------
0000 0000
可以见到 STATUS
中已经没有了 OP_CONNECT
的状态值了。