Number for each enum item?
Asked Answered
L

5

7

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?

Lukasz answered 29/7, 2010 at 7:26 Comment(0)
W
25

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;
    }
}
Winger answered 29/7, 2010 at 7:35 Comment(1)
You should add some parenthesis there: if ((ch.getMask() & CharEnum.A.getMask()) > 0)Subalternate
E
5

(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) {
     ...
  }
Everyone answered 29/7, 2010 at 7:30 Comment(0)
I
2

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.

Imbed answered 29/7, 2010 at 7:35 Comment(0)
E
2

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.

Edge answered 29/7, 2010 at 7:36 Comment(0)
B
2

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.

Benthos answered 29/7, 2010 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.