在實際開發中,往往一個類對象擁有多種權限,每種權限有兩個狀態即有和無,正常情況下,有多少個權限,就需要多少個字段保存相應狀態,如果權限過多,那麼這種方式顯得極其笨重,最近學習了一種用一個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有增權限,其他方法也是通過這種位運算計算得出的結果,不一一演示
}