Link to home
Start Free TrialLog in
Avatar of eugeneng
eugeneng

asked on

how to do enum declaration in Java.

how to convert the following c++ code to Java, I'm interested on the enum part.

#define BASE 0

enum
{
  ZERO = BASE,
  ONE,
  TWO
}

enum Enum1
{
   E0 = ZERO,
   E1,
   E2,
   E3,
   E4,
   E10 = 10,
   E11,
   E12,
};

class test
{
  enum PROTOCOL
  {
    TCP,
    UDP
  };

  PROTOCOL Protocol;
  PROTOCOL GetProtocol() {return Protocol;};
}

class Test2
{
   Enum1 e;
   Test2() {e = E10;}
   Enum1 GetEnum(){return e;};
}
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Yes, objects, enums aren't directly supported in Java, but with a trick (one could call it a pattern), you can create type-safe enums in Java.

The trick:

1. Define a class which is the enum.
2. Make its constructor private.
3. Define public static final members of the same type. These members are the enum values.

I post this to give you an example to play with.

public class NumberEnum {
    public static final ZERO = new NumberEnum();
    public static final BASE = ZERO;
    public static final ONE = new NumberEnum();
    public static final TWO = new NumberEnum();
   
    // private constructor
    private NumberEnum() {}
}

This way you have a group of predefined distinct values of a type which behave very much like an enum.
Oops, I forgot to put NumberEnum here:

public static final NumberEnum ZERO = ...

and so on...
Yes Eugeneng

Elpp Is right
But Elpp I have question Why u need a Class but u could it in a interface. It is always better to put in a interface right.
Please suggest. I use to put this in an interface.

Please refer javaworld for more details abt classes and interfaces.


Shyam
Avatar of sdussinger
sdussinger

Shyam:

Actually this is one place where you don't want to use an interface.  The whole point of defining an enum is that its a bounded set of values. This implies that there should only be a specific set of values for the enum, no more and no less. By using a class and making the constructor private, there is no way for anyone else to create new enum values.  If you made this an interface, then other people could implement the interface and create new enum values.

--Steve
Exactly what the article I posted discusses.
Avatar of eugeneng

ASKER

how do I assigned a specific value to 1 of the enum variable, for example, I would like to assign 7000 to the BASE in below


public class NumberEnum {
   public static final NumberEnum BASE = ...; //how assign 7000 to BASE, and subsequently, the following ONE will have the value of 7001, TWO = 7002, right ?
   public static final NumberEnum ZERO = BASE;
   public static final NumberEnum ONE = new NumberEnum();
   public static final NumberEnum TWO = new NumberEnum

can I do it is this way,

class BASE
{
  private BASE(){};
  public static final int IVR_BASE = 7000;
  public static final int IVR_GENERAL_BASE=  0;
  public static final int IVR_MEDIA_BASE= IVR_BASE + 1000;
  public static final int IVR_CALL_CONTROL_BASE     = IVR_BASE + 2000;
  public static final int IVR_ACD_BASE= IVR_BASE + 4000;
  public static final int IVR_ENUM_BASE     = IVR_BASE + 5000;
}

public class prog
{
  public static void main(String argc[])
  {
     System.out.println("*Hello Enum World ");

/****how do I do the following properly****/

     BASE b;
     b = BASE.IVR_CALL_CONTROL_BASE;
        if (IsMedia(e) == 1)
            System.out.print("This is media base");
        else
            System.out.print("This is not a media base");
       
     public int IsMedia(BASE e)
     {
        if (e == BASE.IVR_MEDIA_BASE)
           return 1
          else
            return 0;
     }
}
If you really need to use 7000 as the value of one of the enums, I would do the following. This follows along with the typesafe enum propsed by other people previously in this thread:

class NumberEnum
{
  private int eValue;

  public static NumberEnum BASE = new NumberEnum (7000);
  public static NumberEnum NEXT = new NumberEnum (7001);

  .
  .
  .

  private NumberEnum (int value)
  {
    eValue = value;
  }

  public boolean equals (int value)
  {
    return (this.eValue == value);
  }
}

Before you go this route, though you really need to ask yourself why the enum has to have the value of 7000. If the answer to that question is "so that I know its a unique value", then you don't need to do this. The fact that the original post talking about typesafe enums created a separate member for each enum in a group ensures that the values will always be unique. You can compare the object references using the standard relational operators just as if the enums were integral values. I.e. NumberEnum.BASE != NumberEnum.NEXT is guaranteed to be true.

On the other hand, if the reason that you need to ensure that this BASE enum has the value of 7000 is being forced on you by some external application or class, then you really don't have a whole lot of choice.  You need to ensure that the BASE enum has a value of 7000 no matter what so you can compare it against an integer coming from some other source. This is where the equals method comes in. By defining the equals method, you can compare the enum values to an integer coming from some other code. In this case NumberEnum.BASE != NumberEnum.NEXT still holds. In addition NumberEnum.BASE.equals(7000) is also valid.

--Steve
how do I assigned a specific value to 1 of the enum variable, for example, I would like to assign 7000 to the BASE in below


public class NumberEnum {
   public static final NumberEnum BASE = ...; //how assign 7000 to BASE, and subsequently, the following ONE will have the value of 7001, TWO = 7002, right ?
   public static final NumberEnum ZERO = BASE;
   public static final NumberEnum ONE = new NumberEnum();
   public static final NumberEnum TWO = new NumberEnum

can I do it is this way,

class BASE
{
  private BASE(){};
  public static final int IVR_BASE = 7000;
  public static final int IVR_GENERAL_BASE=  0;
  public static final int IVR_MEDIA_BASE= IVR_BASE + 1000;
  public static final int IVR_CALL_CONTROL_BASE     = IVR_BASE + 2000;
  public static final int IVR_ACD_BASE= IVR_BASE + 4000;
  public static final int IVR_ENUM_BASE     = IVR_BASE + 5000;
}

public class prog
{
  public static void main(String argc[])
  {
     System.out.println("*Hello Enum World ");

/****how do I do the following properly****/

     BASE b;
     b = BASE.IVR_CALL_CONTROL_BASE;
        if (IsMedia(e) == 1)
            System.out.print("This is media base");
        else
            System.out.print("This is not a media base");
       
     public int IsMedia(BASE e)
     {
        if (e == BASE.IVR_MEDIA_BASE)
           return 1
          else
            return 0;
     }
}
HI Steve

Hey in interface don't you define
like this

public interface Enum
{
          static final String DRIVER="Driver";
          static final int version=2.0
}

Using this interface as Enum
How advantage u have it in class having the same
Please explain me

Shyam
Shyam:

Obviously I was on some kind of mind-altering drug when I made that previous post. My argument there was just wrong :-(...

However, there are still a few problems with using an interface to define a typesafe enum. First, lets assume that using an int as the field value in our enum is bad. Why? Consider this:

interface enum1
{
  public static final int BASE = 1;
}

interface enum2
{
  public static final int BASE2 = 1;
}

Now by using an int here we're effectively allowing that fields of two distinct enums can be equivalent. In essence, enum1.BASE == enum2.BASE2. If we really want a typesafe enum, then a comparison like this should probably not be allowed.

To solve this problem, we define the following:

class enum1
{
  public static final enum1 BASE = new enum1 ();
}

class enum2
{
  public static final enum2 BASE2 = new enum2 ();
}

This enforces that comparisons between enum1 values and enum2 values are invalid. This is most likely the way we want a typesafe enum to behave.

Now imagine that we tried to define them as interfaces.

interface enum1
{
  public static final enum1 BASE = new enum1 ();
}

This can't be done. We can't construct a value for a static member of an interface, because its abstract. So we're left with using something like integer constants which defeats the purpose of typesafe enums.  Or we have to define another class which can be instantiated to hold our enum values. This implies something like this:

interface enum1
{
  class enumValue
  {
  }

  public static final enumValue BASE = new enumValue ();
}

This works, but it requires us to have both an interface and a class to implement the same functionality.

In addition, by defining an interface we're inviting programmers to implement it in their classes. However, why do we even want to implement this interface? It has no behavior that's being defined by the implementing class, so there's no need to implement it. If there's no need to implement it, then it probably shouldn't be an interface.

Sorry for being so long-winded. Hopefully this makes some sort of sense... :-)

BTW, Joshua Block's book "Effective Java Language Programming Guide" has some really good stuff on the use of interfaces and on typesafe enums. If you haven't seen it, take a look. Its well worth the cost...

--Steve

In addition,
can somebody answer my question? please!!
can somebody answer my question? please!!
ASKER CERTIFIED SOLUTION
Avatar of sdussinger
sdussinger

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Oops. At 2:00 in the morning one is guaranteed to make a mistake, and I have :-}

In the previous post, the first example using ints as the enum type, I used EnumBase rather than BaseEnum for enum values. Everywhere where there's an EnumBase in that code should read BaseEnum.

Sorry for the confusion...

--Steve
excellent!! thanx alot sdussinger :)