在很多框架中, 我们都能看到类似 int xxx = 0x0010 这种代码, 我们只知道他表示状态, 很牛x, 但是具体为啥要这样, 或者它是如何表示多个不同状态的却全然不知.
回顾位运算
位运算符号列表:
符号 | 英文名 | 中文名 |
---|---|---|
\ | OR | 或 |
& | AND | 与 |
~ | NOT | 非 |
^ | XOR | 异或 |
>> | - | 右移 |
<< | - | 左移 |
>>> | - | 无符号右移(最高位始终补0) |
每种运算符的运算方式:
1 | 0 // 1, 两个有一个 1 结果为 1, 其他情况都为 0
1 & 0 // 0 两个都为 1 结果为 1, 其他情况都为 0
~ 1 // 0 单目运算, 取运算值的反值
1 ^ 0 // 1 参与运算的两个值不同, 则为 1, 相同则为 0
1 << 1 // 10 将左边的值 左移 指定位数
1010 >> 1 // 101 将左边值 右移 指定位数
标志位: 将一个整数的某一位作为标志位, 并赋予特定的含义
假如我们要保存一个用户的增删查改权限, 四种权限组合, 一共有 16 中状态.
public static int NONE = 0;
public static int ADD = 1;
public static int DELETE = 2;
public static int READ = 4;
public static int UPDATE = 8;
我们通过这几种值表示是否在某个方向,为什么要用这些特定的值?
1 = 0001
2 = 0010
4 = 0100
8 = 1000
这些值都是 2 的次幂, 将这些值转换为二进制, 发现每个值有一个位是 1 其他都是 0, 并且相同位不重复
这样, 每个状态参与位运算始终只影响该转态位的值
再定义一个表示权限的标识 permission, 默认是无任何权限
假如需要添加 READ, ADD 权限
permission |= ADD | READ;
// 0 | 0001 | 0100 = 0101
/**
0000
0001
0100
----
0101
*/
我们添加了两个权限, 分别是 ADD , READ, 则这两个标志位的的值变成了 1
如何检查是否拥有某个权限
boolean canRead = (permission & READ) != 0
// 0101 & 0100 = 0100 = ADD
/**
0101
0100
----
0100
*/
如何移除某个权限
permission ^= READ
// 0101 ^ 0100 = 0001
/**
0101
0100
----
0001
*/
另一方式移除某个权限
permission &= ~ READ
// 0101 & 1011 = 0001
/**
~0100
----
1011
&0101
----
0001
*/
标志位的优势
标志位可以减少很多代码, 理解简单
如果我们用一个 boolean 给一个对象添加 READ 和 ADD 权限
setCanRead(true);
setCanAdd(true);
setCanUpdate(false);
setCanDelete(false);
用标志位
addPermission(READ | ADD);
用 boolean 判断是否拥有 READ 和 ADD 权限
isCanRead();
isCanAdd();
用标志位
hasPermission(ADD | READ);
用 boolean 判断是否拥只有 READ 和 ADD 权限
isCanAdd() isCanRead && !isCanUpdate() && !isCanDelete()
用标志位
isJustAllow(READ | ADD);
上例中的代码
class Permission {
public static final int NONE = 0;
public static final int ADD = 1;
public static final int DELETE = 2;
public static final int READ = 4;
public static final int UPDATE = 8;
private int mPermission = NONE;
public void addPermission(int permission){
mPermission |= permission;
}
public boolean hasPermission(int permission){
return (mPermission & permission) != NONE;
}
public boolean isJustAllow(int permission){
return mPermission == permission;
}
public void removePermission(int permission){
mPermission ^= permission;
}
}
转载自:https://blog.csdn.net/jdsjlzx/article/details/93977574