Java位运算

Java bit operations

我正在尝试创建一个 Java class 来保存一些设置标志。 Class 成员:

这些可以是enabled/disabled。 我想用按位操作来做,但我想知道这是否可能,因为我不会在给定时间设置所有操作。我只想设置一个,其他的保持不变。

给出一个当前状态0100,所以只有FOOTER启用,是否可以启用HEADER并保留FOOTER标志值?

如果我的场景可行?

主要Class

package foo;

public class Main {

  private static final SectionVisible sectionVisible = new SectionVisible(); 

  public static void main(String[] args) {    
    // Enable FOOTER only
    sectionVisible.setValue(2); // 00000010
    printState();
    // Enable LEFT_SECTION but preserve FOOTER's value
    sectionVisible.setValue(4); // 00000100
    printState();
  }

  private static void printState() {
    System.out.println("header=" + sectionVisible.header());
    System.out.println("footer=" + sectionVisible.footer());
    System.out.println("leftSection=" + sectionVisible.leftSection());
    System.out.println("----------------------------------------------------");
  }

}

可见部分Class

package foo;

class SectionVisible {

  private static final Integer LEFT_SECTION_MASK = 4;
  private static final Integer LEFT_SECTION_OFFSET = 2;

  private static final Integer FOOTER_MASK = 2;
  private static final Integer FOOTER_OFFSET = 1;

  private static final Integer HEADER_MASK = 1;
  private static final Integer HEADER_OFFSET = 0;

  private Integer value;

  public Integer header() {
    return (value & HEADER_MASK) >> HEADER_OFFSET;
  }

  public Integer footer() {
    return (value & FOOTER_MASK) >> FOOTER_OFFSET;
  }

  public Integer leftSection() {
    return (value & LEFT_SECTION_MASK) >> LEFT_SECTION_OFFSET;
  }

  public void setValue(Integer value) {
    System.out.println(
        "Setting value to " + value + ":" + Integer.toBinaryString(value));
    this.value = value;
  }

}

执行日志

Setting value to 2:10
header=0
footer=1
leftSection=0
----------------------------------------------------
Setting value to 4:100
header=0
footer=0
leftSection=1
----------------------------------------------------

问题是,当我设置 LEFT_SECTION 的值时,我丢失了 FOOTER 的值。

使用按位运算符 &, |和 ^:

flags |= HEADER; // enable HEADER
if ((flags&FOOTER) != 0)
    ... do something when FOOTER is enabled...
     static final int HEADER = 1;
     static final int FOOTER = 2;
     static final int LEFT_SECTION = 4;
     static final int RIGHT_SECTION = 8;

     int flags = 0;

     boolean isEnabledFooter() {
         return (flags & FOOTER) != 0;
     }

     void enableFooter() {
         flags |= FOOTER;
     }

     void disableFooter() {
         flags &= ~FOOTER;
     }

每个状态都必须由一个唯一的位掩码表示,通常称为 flag(可以是单个位,也可以是多个位,具体取决于状态的数量).

public final static int HEADER = 0b0001;
public final static int FOOTER = 0b0010;
public final static int LEFT_SECTION = 0b0100;
public final static int RIGHT_SECTION = 0b1000;

您还需要打包状态:

private int states=0;

Flags的获取和设置如下(位运算):

public boolean get (int flag) {
    return (states & flag) != 0;
}

public void set (int flag, boolean value) {
    states = value ? (states | flag) : (states & ~flag);
}

用法:

// set header 
set(HEADER, true);
// unset header 
set(HEADER, false);
// read header 
boolean value = get(HEADER);