使用Java中的按位运算符屏蔽选项

时间:2014-03-28 23:41:51

标签: java bit-manipulation

我想知道如何屏蔽值,以便我可以设置配置。让我知道我有常数 Options.A = 0Options.B = 1等等......

builder.setOption( Option.A & Option.C ); // Or should I use '|' operator?

这意味着

Option.A    Option.B    Option.C    Option.D
    1           0           1           0

由于1010是数字10的二进制,因此它意味着builder.option = 10;,但在实际实现中我会有switch个案例,可以将其比较:

// inside builder.someFunction();
switch(this.option) {
    case Option.A & Option.C:

注意:请纠正我,如果这不是你如何使用按位运算符来掩盖值,我已经阅读了很多并且不太了解它,所以如果这是错的我可能需要switch-case这样的例子。

PS:我从Android框架中获取了一行代码,如下所示:

view.gravity = Gravity.TOP | Gravity.LEFT;

这是我想要实现的类似行为。

3 个答案:

答案 0 :(得分:1)

我从来没有实现过这个,但它发生在我身上:

对于第一个问题,是的,你需要使用| (而不是&)正确地积累选项

如果你要在一个变量中累积选项,那么要检查哪些选项是ON我会使用

for(int i=0;i<32;i++){
    if(i&options){//check if i-th option is ON
        option_function(i);
    }
}

并在option_function()内部执行切换案例。

void option_function(int i){
    switch(i) {
        case Option.A:
            ....
}

}

答案 1 :(得分:1)

首先,理论:

(1)我们忽略数据类型,假设您有4个选项:

Option.A    Option.B    Option.C    Option.D

然后你需要使用一个4位宽的变量来表示它们。假设Option.A是最高(最左侧)位,Option.D是最低位(最右侧)。然后这个变量看起来:

Option.A    Option.B    Option.C    Option.D
  bit3        bit2        bit1        bit0 

其范围为0000~1111,代表2 ^ 4 = 16种不同组合。

(2)对于位操作,首先应为每个选项定义掩码:

var Mask.A = 1000;
var Mask.B = 0100;
var Mask.C = 0010;
var Mask.D = 0001;

&lt; 1&gt;如果要表示具有Option.B和Option.C的值,可以使用OR操作:

var v_B_and_C = Mask.B | Mask.C = 0100 | 0010 = 0110;

&lt; 2&gt;如果要检查某个值是否包含Option.B,请使用AND,然后比较结果:

var some_v = 1101;
var result = some_v & Mask.B = 1101 & 0100 = 0100;
if(result != 0000) {// Contains Option.B! }
else {// ==0000. Not contains Option.B! }

&lt; 3&gt;如果您想撤销某个值,可以使用NOT / XOR

var some_v = 0011;
var reversion_v = ~some_v = ~0011 = 1100;
// you can also use XOR(^) between a value and an all-1 constant
var reversion_v = some_v ^ 1111 = 0011 ^ 1111 = 1100;

&lt; 4&gt;如果您想知道两个值之间的差异,可以使用XOR

var v_1 = 1100, v_2 = 0110;
var diff = v_1 ^ v_2 = 1100 ^ 0110 = 1010 // Means bit3, bit1 are different!

&lt; 5&gt;对于其他用法,请参考:Bitwise Operation

其次,在Java中练习:

(1)你需要明确的第一件事是你需要代表多少Options(bits)? 因为不同的数据类型具有不同的宽度(表示不同的范围):

  • short:2Bytes,16bit,代表2 ^ 16 = 65536种组合。
  • int:4Bytes,32bit,代表2 ^ 32 = 4294967296种组合。
  • long:8By,64bit,代表2 ^ 64 = 18446744073709551616 组合。

如果您需要超过64个选项,您可能需要使用数组(int [] / long [])或方便的类:java.util.BitSet

(2)如果要通过数组实现自己,请使用按位运算关键字(&amp;,|,^,〜,&lt;&lt;&lt;,&gt;&gt;&gt;)。有一个以二进制格式打印出int的提示:

int i = 0x80000000;
System.out.println(Integer.toBinaryString(i));
// Print: 10000000000000000000000000000000

(3)我建议使用java.util.BitSet类,除非你有理由必须自己实现。例如:

import java.util.BitSet;

public class Main {
   public static void main(String[] args) {
      // Create a BitSet object, which can store 128 Options.
      BitSet bs = new BitSet(128);
      bs.set(0);// equal to bs.set(0,true), set bit0 to 1.
      bs.set(64,true); // Set bit64

      // Returns the long array used in BitSet
      long[] longs = bs.toLongArray();

      System.out.println(longs.length);  // 2
      System.out.println(longs[0]); // 1
      System.out.println(longs[1]); // 1
      System.out.println(longs[0] ==longs[1]);  // true
   }
}

其他用法,see the java docs

答案 2 :(得分:0)

为什么不创建一个更易于阅读和使用标准API的类?

public class Permissions { 

    final BitSet permissions;

    public Permissions() {
        permissions = new BitSet();
    }

    public void setPermission(int p) {
        permissions.set(p);
    }
}