Denua 博客

用标志位表示状态

发布时间: 2019-06-05 19:14   分类 : Java    标签: 其他 浏览: 2136   

在很多框架中, 我们都能看到类似 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, 默认是无任何权限

private int permission = NONE;

假如需要添加 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;
    }
}

(完)

评论    

Copyright denua denua.cn