转载

[Java] 位运算简化代码逻辑

Review同事代码时候,看到一段涉及到USB的逻辑代码,他是这样写的

private boolean isUsbConnected;
private boolean isUsbConfigured;
private boolean isUsbModeAccessory;
private boolean isUsbModeAdb;
private boolean isUsbModeMTP;
...

然后代码逻辑里是大量的成员变量的判断,显得非常臃肿而且难读懂,大量的if-else判断让代码逻辑很脆弱,稍微一个情况没考虑好就会出现难以排查的bug。

所以这种情况使用位掩码进行处理会更简单:

private static final int FLAG_USB_CONNECTED = 0x1;
private static final int FLAG_USB_CONFIGURED = 0x1 << 1;
private static final int FLAG_USB_MODE_ACY = 0x1 << 2;
private static final int FLAG_USB_MODE_ADB = 0x1 << 3;
private static final int FLAG_USB_MODE_MTP = 0x1 << 4;
...
private int mUsbState;

public void addUsbState(int flag) {
 	mUsbState |= flag; 
}

public void removeUsbState(int flag) {
  mUsbState &= ~flag;
}

public boolean isUsbStateEnable(int flag) {
  return (mUsbState & flag) == flag;
}

简单分析一下这样写的好处:

FLAG_USB_CONNECTED = 0001
FLAG_USB_CONFIGURED = 0010
FLAG_USB_MODE_ACY = 0100
FLAG_USB_MODE_ADB = 1000

通过移位,使得每一位都有独立的代表的意义,1代表enable,0代表disable。

如果要 添加状态 (Java里int值默认赋值为0):

public void addUsbState(int flag) {
 	mUsbState |= flag; 
}

假设添加accessory状态FLAG_USB_MODE_ACY

0000 |= 0100 -> 0100

所以mUsbState就是0100的状态了。

继续添加FLAG_USB_MODE_ADB状态

0100 |= 1000 -> 1100

然后是移除状态:

public void removeUsbState(int flag) {
  mUsbState &= ~flag;
}

比如接着上面移除FLAG_USB_MODE_ADB状态

1100 &= ~1000
-> 1100 &= 0111
-> 0100

如果移除一个不存在的状态比如FLAG_USB_CONFIGURED

0100 &= ~0010
-> 0100 &= 1101
-> 0100

可以看到并不会对当前状态造成任何影响。

最后看一下 检查状态

public boolean isUsbStateEnable(int flag) {
  return (mUsbState & flag) == flag;
}

首先检查一下当前拥有的状态:

(0100 & 0100) == 0100
-> 0100 == 0100
-> true

可以检测到该状态。然后换一个状态:

(0100 & 1000) == 1000
-> 0000 == 1000
-> false

没有检测到该状态。

所以,通过三个简单的方法,就可以检查一个变量里保存的所有状态,避免了使用大量bool变量进行挨个检查。简化了代码,增加代码可读性,并且使代码更加稳定。

原文  http://wossoneri.github.io/2019/12/09/[Java]Bit-mask-code/
正文到此结束
Loading...