在实际开发中,往往一个类对象拥有多种权限,每种权限有两个状态即有和无,正常情况下,有多少个权限,就需要多少个字段保存相应状态,如果权限过多,那么这种方式显得极其笨重,最近学习了一种用一个int字段实现的权限管理的方式,方便快捷,实现原理简单,大大简化操作,用了一上午时间研究,简单实现了8个权限的管理(实际上int字段可以管理32位,与8位管理没有本质区别),现就实现过程及内部原理做一个简单总结
1.需要了解的基础知识 ——JAJA中基本数据类型所占的空间:
java基本数据类型 四类八种:byte(1字节),short(2字节),int(4字节),long(8字节),char(1字节),boolean(1字节),float(4字节),double(8字节),其中1字节=8位,所以 int类型在计算机内存中占32位
2.需要了解的基础知识 ——JAVA中的位运算符,这里用到的 & (与) 、|(或) 、 ~(非)
简单运算(都是二进制的数据)
1 & 1 = 1 1 | 1 = 1 ~0 = 1
1 & 0 = 0 1 | 0 = 1 ~1 = 0
0 & 1 = 0 0 | 1 = 1
0 & 0 =0 0 | 0 = 0
了解以上基础知识后,简单的写一个小demo,尝试一下利用位运算管理权限的方便之处(如果是十进制的数参与位运算,首先将十进制的数转换为二进制,运算结束后再转为十进制,这些都是计算机自动完成的)
public class Authority {
//新增权限
private static final int ALLOW_INSERT = 1 << 0;
//删除权限
private static final int ALLOW_DELETE = 1 << 1;
//修改权限
private static final int ALLOW_UPDATE = 1 << 2;
//查看权限
private static final int ALLOW_SELECT = 1 << 3;
//可读权限
private static final int ALLOW_READ = 1 << 4;
//可写权限
private static final int ALLOW_WRITE = 1 << 5;
//复制权限
private static final int ALLOW_COPY = 1 << 6;
//只读权限
private static final int ALLOW_READONLY = 1 << 7;
//用来保存当前存在的权限,即用这一个字段,保存8种权限状态
private int state;
//设置权限,1个或多个
public void setAuto(int auto) {
state = auto;
}
//用来增加一个权限,一个或多个
public void addAuto(int auto) {
state = state | auto ;
}
//用来删除一个权限
public void delAuto(int auto) {
state = state &~auto;
}
//用来查看是否有某种权限
public boolean isAllow(int auto) {
return ((state & auto) == auto);
}
//用来查看是否没有某种权限
public boolean isNotAllow(int auto) {
return ((state & auto) == 0);
}
}
public static void look(Authority auto) {
System.out.println("ALLOW_INSERT 有权限:"+ auto.isAllow(ALLOW_INSERT));
System.out.println("ALLOW_DELETE 有权限:"+ auto.isAllow(ALLOW_DELETE));
System.out.println("ALLOW_UPDATE 有权限:"+ auto.isAllow(ALLOW_UPDATE));
System.out.println("ALLOW_SELECT 有权限:"+ auto.isAllow(ALLOW_SELECT));
System.out.println("ALLOW_READ 有权限:"+ auto.isAllow(ALLOW_READ));
System.out.println("ALLOW_WRITE 有权限:"+ auto.isAllow(ALLOW_WRITE));
System.out.println("ALLOW_COPY 有权限:"+ auto.isAllow(ALLOW_COPY));
System.out.println("ALLOW_READONLY 有权限:"+ auto.isAllow(ALLOW_READONLY));
}
以上就是用int字段管理8个权限状态的demo全部代码,这8个权限的状态是我随便起的,不要在意这些细节
写一个测试方法验证一下
public static void main (String[] args){
//测试一:设置某个对象拥有8种权限
Authority auto = new Authority();
auto.setAuto((1 << 8) -1);
look(auto);
打印结果显示所有权限都为 true
//测试二 在所有权限都有的基础上,删除 增删改查权限
auto.delAuto(ALLOW_INSERT | ALLOW_DELETE | ALLOW_UPDATE | ALLOW_SELECT);
look(auto);
打印结果显示 增删改查权限为false
//测试三 在测试二基础上增加 删除权限
auto.addAuto(ALLOW_DELETE );
look(auto);
打印结果显示删除权限增加成功
到这里基本功能演示完毕,一个int字段可以保存多种状态,下面简单解释一下内部原理
1.首先先定义8种状态,每种状态都是在二进制下位数左移得到的,即
0000 0000 0000 0000 0000 0000 0000 0001 代表 1 << 0;
由于这里演示8种状态,只写8位,前面的 0 全部省略
0000 0001 1 << 0 ALLOW_INSERT
0000 0010 1 << 1 ALLOW_DELETE
0000 0100 1 << 2 ALLOW_UPDATE
0000 1000 1 << 3 ALLOW_SELECT
0001 0000 1 << 4 ALLOW_READ
0010 0000 1 << 5 ALLOW_WRITE
0100 0000 1 << 6 ALLOW_COPY
1000 0000 1 << 7 ALLOW_READONLY
以上不难看出,这8个位上,有1的代表有权限,有0的代表无权限,这样每个位分别控制一种权限,8个位的组合就可以实现8种权限的管理
1.设置权限 setAuto(int auto){
state = auto;
}
其实现是这样,传进去一个int值,一个值代表一个权限,可以传入多个。用位运算符号 “|” 连接参数 ,比如 传入增删权限
增权限 ALLOW_INSERT 其二进制形式 0000 0001
删权限 ALLOW_DELETE 其二进制形式 0000 0010
根据位运算原理,两个二进制的数求或
0000 0001
| 0000 0010
0000 0011
不难看出后两位增删权限都是1,这说明目前有增删权限,其余权限都为0即没有权限
2.删除权限 public void delAuto(int auto) {
state = state &~auto;
}
代码解释:设置state状态为 当前状态 与上 传进来的int值的求非,例如目前有增删权限,需要删除增权限
根据位运算原理 0000 0011 & ~ 0000 0001
第一步 ~ 0000 0001 的值为 1111 1110
第二部 0000 0011 & 1111 1110
0000 0011
& 1111 1110
0000 0010
得到结果 0000 0010 可以看出,增加权限位上的数字为0 ,代表没有增权限,只有删权限
3.查看是否拥某个有权限
public boolean isAllow(int auto) {
return ((state & auto) == auto);
}
设当前 拥有增删权限 0000 0011
传入int值 ALLOW_INSERT 其二进制是 0000 0001,代表查看是否有增权限
(0000 0011 & 0000 0001)的值为 0000 0001
上面提到,如果是位运算,计算机会将数字转为二进制计算,再将结果转为十进制
==是逻辑运算符,需要转成十进制计算
0000 0001 的十进制是1 ,传入的参数 0000 0001 也是 1 ,1 == 1 结果为true
即0000 0011有增权限,其他方法也是通过这种位运算计算得出的结果,不一一演示
}