&(与)
、~(非)
、|(或)
、^(异或)
、<<(左移位)
、>>(右移位)
这些都是位运算符,在项目中经常使用在状态、权限、标记等功能上。比如有增删改查四种权限,给员工增加其中的一种或几种权限;查看员工是否具备某种权限;删除员工具备的某种权限,这都就可以用位运算符解决。
代码示例
通过位掩码控制员工权限
public class EmployeePermission {
// 查询权限,二进制第1位,0表示无权限,1表示有权限
public static final int SEARCH_PERMISSION = 1 << 0; // 0001
// 新建权限,二进制第2位,0表示无权限,1表示有权限
public static final int ADD_PERMISSION = 1 << 1; // 0010
// 编辑权限,二进制第3位,0表示无权限,1表示有权限
public static final int EDIT_PERMISSION = 1 << 2; // 0100
// 删除权限,二进制第4位,0表示无权限,1表示有权限
public static final int DELETE_PERMISSION = 1 << 3; // 1000
// 员工现有权限
private int employeePermission;
/**
* 是否拥某些权限
*/
public boolean isHavePermission(int permission) {
return (employeePermission & permission) == permission;
}
/**
* 重新设置权限
*/
public void ResetPermission(int permission) {
employeePermission = permission;
}
/**
* 添加一项或多项权限
*/
public void addPermistion(int permission) {
employeePermission |= permission;
// employeePermission += permission; // 效果与上一行代码一致,用或(|)运算符方便从二进制的角度去理解
}
/**
* 删除一项或多项权限
*/
public void delPermistion(int permission) {
employeePermission &= ~permission;
}
}
employeePermission
变量二进制的四位数字分别表示员工具有的四种权限状态,每一位的0和1分别表示其中一个权限有无。下面的列表中展示了十进制数对应的转化后的二进制数,以及二进制数字背后分别代表的权限含义。
employeePermission | 查询权限 | 新建权限 | 编辑权限 | 删除权限 | 含义 |
---|---|---|---|---|---|
1(0001) | 0 | 0 | 0 | 1 | 仅拥有删除权限 |
15(1111) | 1 | 1 | 1 | 1 | 拥有所有四项权限 |
0(0000) | 0 | 0 | 0 | 0 | 不具有任何权限 |
6(0110) | 0 | 1 | 1 | 0 | 有用新建与编辑权限 |
要给员工同时添加「编辑权限」、「查询权限」与「删除权限」,只需下面一条简单的即可实现
employee.addPermistion(EmployeePermission.SEARCH_PERMISSION | EmployeePermission.EDIT_PERMISSION | EmployeePermission.DELETE_PERMISSION);
从上面的代码例子中可以看出,位运算不仅理解简单同时因为二进制代码的位运算属于底层,运算效率很高。若是不用位掩码,那代码会变成什么样子呢?
public class EmployeePermissionOld {
// 查询权限
public boolean searchPermission;
// 添加权限
public boolean addPermission;
// 编辑权限
public boolean editPermission;
// 删除权限
public boolean delPermission;
// get 与 set 方法省略,通过 get 和 set 方法来设置与获取权限
}
这时要给员工同时添加「编辑权限」、「查询权限」与「删除权限」
employee.setSearchPermission(true);
employee.setEditPermission(true);
employee.setDelPermission(true);
经过这样的简单对比会发现使用位掩码还能减少代码数量,让操作看上去更简洁。
位掩码的其他形态
有时候在项目中会看到下面这种写法
#define DEBUG_PROCESS 0x00000001 // 十进制 1 二进制 00000001
#define DEBUG_ONLY_THIS_PROCESS 0x00000002 // 十进制 2 二进制 00000010
#define CREATE_SUSPENDED 0x00000004 // 十进制 4 二进制 00000100
#define DETACHED_PROCESS 0x00000008 // 十进制 8 二进制 00001000
#define CREATE_NEW_CONSOLE 0x00000010 // 十进制 16 二进制 00010000
#define NORMAL_PRIORITY_CLASS 0x00000020 // 十进制 32 二进制 00100000
这种十六进制的表示方式与之前的移位运算的例子道理是一样的,只不过换了种表现形式。在实际项目中用十六进制表示更频繁,这里有使用习惯的差异,同时因为十六进制的一位等于二进制的四位,这让十六进制看起来会更加直观。例如十六进制 0x0FFF 等于二进制的 111111111111(12个1)。