How to remove a flag in Java
Asked Answered
S

3

29

Hi I need to remove a flag in Java. I have the following constants:

public final static int OPTION_A = 0x0001;
public final static int OPTION_B = 0x0002;
public final static int OPTION_C = 0x0004;
public final static int OPTION_D = 0x0008;
public final static int OPTION_E = 0x0010;
public final static int DEFAULT_OPTIONS =
       OPTION_A | OPTION_B | OPTION_C | OPTION_D | OPTION_E;

I want to remove, for example OPTION_E from default options. Why is not the following code correct?

// remove option E from defaul options:
int result = DEFATUL_OPTIONS;
result |= ~OPTION_E;
Silas answered 29/9, 2011 at 10:5 Comment(1)
What does the JVM tell you? Wouldn't running it be faster than waiting for an answer to come back from SO? You could have had this done three times by now.Tiedeman
C
52

|= performs a bitwise or, so you're effectively "adding" all the flags other than OPTION_E. You want &= (bitwise and) to say you want to retain all the flags other than OPTION_E:

result &= ~OPTION_E;

However, a better approach would be to use enums and EnumSet to start with:

EnumSet<Option> options = EnumSet.of(Option.A, Option.B, Option.C,
                                     Option.D, Option.E);
options.remove(Option.E);
Cyanamide answered 29/9, 2011 at 10:7 Comment(8)
It has me listed as downvoting this. I think it was a mistake, and it was too long ago so now I can't undo it!Maurita
EnumSet is very verbose compared to bitwise operations. What are benefits of EnumSet that make you believe it's a better approach?Refectory
@RestInPeace: All the normal reasons that enums are better than named int values... mostly type safety (two int constants are compatible even if they're really unrelated - but two enum values aren't) and power (enums are polymorphic, can have (preferrably immutable) state etc). There was a question about that recently, but I can't immediately find it.Cyanamide
@JonSkeet You're right about type safety and polymorphism but with EnumSet can you do stuffs like XOR easily? Could BitSet be another alternative? With BitSet you can do XOR NOR etc.Refectory
@RestInPeace: Well it's a set, so you can do set-based operations, and there's complementOf to help. I think the ability to do XOR and NOR operations would be a very poor reason to abandon type safety.Cyanamide
Dennis Ritchie is turning over in his grave (RIP).Xylography
Thanks and why using EnumSet is a better approach?Mistrial
@ucMedia: See earlier comments.Cyanamide
D
10

You must write

result &= ~OPTION_E;

Longer explanation:

You must think in bits:

~OPTION_E    // 0x0010 -> 0xFFEF
DEFATUL_OPTIONS //     -> 0x001F
0xFFEF | 0x001F //     -> 0xFFFF
0XFFEF & 0x001F //     -> 0x000F

The OR will never clear 1 bits, it will at most set some more. AND on the other hand will clear bits.

Decarburize answered 29/9, 2011 at 10:6 Comment(0)
S
6

You should use the and operator instead of or:

result &= ~OPTION_E;

One way to think about it is that |= sets bits whereas &= clears bits:

result |= 1;  // set the least-significant bit
result &= ~1; // clear the least-significant bit
Something answered 29/9, 2011 at 10:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.