Java位操作

时间:2016-01-19 08:13:07

标签: java bit-manipulation

我正在尝试创建一个包含一些设置标志的Java类。 班级成员:

  • HEADER
  • FOOTER
  • LEFT_SECTION
  • RIGHT_SECTION

可以启用/禁用这些功能。 我想用有点操作来做这件事,但我想知道是否可能,因为我不会在给定时间设置所有这些。我只想设置一个,让其他人保持不变。

提供当前状态0100,因此只启用FOOTER,是否可以启用HEADER并保留FOOTER标记值?

如果我的方案可行?

主类

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("----------------------------------------------------");
  }

}

SectionVisible 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的值。

3 个答案:

答案 0 :(得分:1)

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

flags |= HEADER; // enable HEADER
if ((flags&FOOTER) != 0)
    ... do something when FOOTER is enabled...

答案 1 :(得分:1)

     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;
     }

答案 2 :(得分:0)

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

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;

标志可以如下获取和设置(位算术):

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);