How to use bit flags
Short answer
Give each flag its own bit (1, 2, 4, 8...), combine flags with | and check them with &:
static final int READ = 1;
static final int WRITE = 1 << 1;
static final int DELETE = 1 << 2;
void main() {
int perms = READ | WRITE;
IO.println((perms & WRITE) != 0);
IO.println((perms & DELETE) != 0);
}Output:
true
falseSet, clear, toggle
|= turns a bit on, &= ~ turns it off, ^= toggles it:
static final int READ = 1;
static final int WRITE = 1 << 1;
static final int DELETE = 1 << 2;
void main() {
int perms = READ;
perms |= DELETE;
IO.println(Integer.toBinaryString(perms));
perms &= ~READ;
IO.println(Integer.toBinaryString(perms));
perms ^= WRITE;
IO.println(Integer.toBinaryString(perms));
}Output:
101
100
110All flags at once
Check that all required flags are on, and count the ones that are on:
static final int READ = 1;
static final int WRITE = 1 << 1;
static final int DELETE = 1 << 2;
void main() {
int perms = READ | WRITE;
int required = READ | WRITE;
IO.println((perms & required) == required);
IO.println(Integer.bitCount(perms));
}Output:
true
2EnumSet instead of flags
In new code flags are easier to keep in an EnumSet: inside it works the same way, but the code reads better and the output is clearer:
enum Permission { READ, WRITE, DELETE }
void main() {
EnumSet<Permission> perms = EnumSet.of(Permission.READ, Permission.WRITE);
perms.remove(Permission.READ);
perms.add(Permission.DELETE);
IO.println(perms);
IO.println(perms.contains(Permission.WRITE));
}Output:
[WRITE, DELETE]
trueCommon mistake
Forgetting the parentheses. & has lower precedence than !=, so the expression without parentheses does not compile:
static final int WRITE = 2;
void main() {
int perms = 3;
if (perms & WRITE != 0) {
IO.println("can write");
}
}Output:
Main.java:5: error: bad operand types for binary operator '&'The correct form is (perms & WRITE) != 0. Another mistake is numbering flags 1, 2, 3: 3 has two bits set and equals 1 | 2.
Functions used in this recipe
- & | ^ ~ << >> >>> — Bitwise operators work with individual bits of integers: AND, OR, XOR, NOT and shifts.
- EnumSet — A set of values of one enum. Works like a set of bit flags, but with readable code.
- Integer.toBinaryString() — Writes a number in binary. Related methods are toHexString() and toOctalString().
- += -= *= /= — Performs an operation and stores the result back in the same variable.