Java位运算
Java bit operations
我正在尝试创建一个 Java class 来保存一些设置标志。
Class 成员:
- HEADER
- 页脚
- LEFT_SECTION
- RIGHT_SECTION
这些可以是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);
我正在尝试创建一个 Java class 来保存一些设置标志。 Class 成员:
- HEADER
- 页脚
- LEFT_SECTION
- RIGHT_SECTION
这些可以是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);