views:

125

answers:

5

Is it possible to define something like this in java?

C# code:

public enum Character
{
    A = 1,

    B = 2,

    C = 4,

    D = 8

}


...

Character ch = /* from user */

if(ch & Character.A)
{
    // some operation...
}

for example if ch set to Character.B then result of if will be false:

ch = 00000000 00000000 00000000 00000010
A  = 00000000 00000000 00000000 00000001
------------------------------------------
&    00000000 00000000 00000000 00000000

I want to implement something like that! Is it ever possible in Java?

+1  A: 

(Of course, choosing Character as the name of your enum is very confusing as it creates a conflict with java.lang.Character which is automatically imported into every compilation unit)

You can use the ordinal() method to get the integer associated with an enum constant. Anyway, I got a feeling that what you are trying to achieve may be realized by enum-defined methods. I mean, Java's enum are more powerful than C/C++'s because you can associate behavior with them.

  public enum Chr {
    A {
       @Override public void doSomething(int c) {
         // some operation ...
       }
    },
    B,
    C,
    D;

    public void doSomething(int c) { 
      // some default behavior
    }
  }

Following your comment:

You can define a field which will hold this value, and have the constructor initialize it, as follows:

  public enum Chr {
    A(1),
    B(2),
    C(4),
    D(8)
    ;

    public Chr(int n) { value = n; }        
    public final int value;
  }



  Character ch = ... // from user
  if(ch & Chr.A.value) {
     ...
  }
Itay
+1  A: 

You could do something like that using Enum.ordinal(), but it would be really bad design. You should use == for equality comparisons and EnumSet for set operations.

Michael Borgwardt
+8  A: 

Well, you can nearly do that:

public enum CharEnum // Let's avoid java.lang.* clashes
{
    A(1), B(2), C(4), D(8);

    private final int mask;

    private CharEnum(int mask)
    {
        this.mask = mask;
    }

    public int getMask()
    {
        return mask;
    }
}

Then:

CharEnum ch = /* from user */

if ((ch.getMask() & CharEnum.A.getMask()) > 0)
{
    // some operation...
}

This can be useful in some situations, but as Michael said you should definitely look at EnumSet for general "set of values" options.

If you do decide to go for an enum with values, you can put extra logic within the enum itself:

public enum CharEnum
{
    // Other code as before

    public boolean overlapsWith(CharEnum ch)
    {
        return (ch.mask & mask) > 0;
    }
}
Jon Skeet
True Soft
Thank you! Don't wory about "Character" keyword! It was just a sample!!! My enum name is something completely different!
Jalal Amini
WOW! Java is great!!!
Jalal Amini
@True Soft: Fixed, thanks.
Jon Skeet
+1  A: 

I agree with Itay, and to get a bit further I'll recommend the reading of Effective Java Second Edition having a full chapter really interesting on Java enums.

Manuel Selva
+1  A: 

I agree with Michael Borgwardt and Jon Skeet that an EnumSet is worth looking at. I would have picked EnumSet over bitwise operations like you've got, so I will demonstrate how to use EnumSet.

 

It looks like your Character enum (let's call it CharEnum from now on) CharEnum is being used like a bit field, where each enum has an int value with just one bit set:

A  = 00000000 00000000 00000000 00000001
B  = 00000000 00000000 00000000 00000010
C  = 00000000 00000000 00000000 00000100
D  = 00000000 00000000 00000000 00001000

This is very similar to what an EnumSet does for you; it has an internal bit vector that automatically assigns each enum to a bit on a long. As the JavaDoc for it says, "The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags."

Here's an example of how to use it

public enum CharEnum {
    A, B, C, D;
}

and then

EnumSet<CharEnum> ch = /* from user */

if (ch.contains(CharEnum.A)) {
    // some operation...
}

No need to specify bits anywhere, so it's much simpler code!

A warning: this only works because the enum values in your C# example have only one bit set each. If you had an enum value like this:

E  = 00011000 01110111 11100101 10000101

then an EnumSet would not be appropriate. In that case you should look at one of the other answers here.

gutch