Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C-like enum in Java

I'm trying to find a Java equivalent for the following convenience in C++:

enum {
  ANIMAL_CAT = 0,
  ANIMAL_RAT,
  ANIMAL_BAT, ...
  NUM_ANIMALS
};

Animal animals[NUM_ANIMALS];

animals[ANIMAL_CAT].mNumLegs = 4;
animals[ANIMAL_RAT].mNumLegs = 4; ...

I know this isn't the prettiest thing in the world, but I can add a new ANIMAL_xxx anywhere in the enum and all the following entries will be automatically adjusted. Is there a clean way to do this in Java?


Thanks for the responses, but I may have alluded to a greater simplicity than I intended.

I'm working on a game, where there's a physics, AI engine, etc. I'm trying to consolidate all the information I need for each type of entity (some have only a physical manifestation, while some have both phys and AI, etc...), so that I can easily add/modify types (so, animal is a bad example, because I may need rocks, plants, etc...).

I'm using a class to store the type info, while other classes rely on that class to look up the attributes (dimensions, bitmap index, hasAi, etc...) In the end, I'm trying to clean up something similar to the following, while allowing me to easily add new types:

class UnitTypeInfo {
  UnitTypeInfo() {
    mTypes = new TypeInfo[NUM_TYPES];

    // and allocate...

    // initialize TypeInfos here
    mTypes[TYPE_CAT].mType = TYPE_CAT;
    mTypes[TYPE_CAT].mMass = 10.0f;
    mTypes[TYPE_CAT] ...

    mTypes[TYPE_ROCK].mType = TYPE_ROCK;
    ...
  }

  public class TypeInfo {
    public int mType;
    public int mRawResourceHandle;
    public float mMass;
    public Vector2d mDimensions;
    public float mHealth;
    public boolean mHasAi;
    ...
  }

  public static final int TYPE_CAT = 0;
  public static final int TYPE_ROCK = 1;
  public static final int TYPE_TREE = 2; ...
  public static final int NUM_TYPES = ???; // the last TYPE_ + 1

  public TypeInfo mTypes[];
}

Now, this seems like some sort of XML implementation might be the 'right' thing to do, but I'm not sure about how to do that (new to Java). Anyhow, the other classes can easily just use unitTypeInfo.mTypes[UnitTypeInfo.TYPE_CAT].mMass (instantiated) to look up the cat's mass. However, if I want to add a TYPE_DOG underneath the TYPE_CAT definition, I have to update everything underneath it (lazy, I know, but let's figure there are a few more types.)

Enums offer an easy solution to this problem in C++, but in Java, the simplest solution I can can up with now requires something like: unitTypeInfo.mTypes[UnitTypeInfo.mTypeEnum.TYPE_CAT.ordinal()].mMass - and while I suppose this isn't much worse than my already crummy solution, it does add a fair bit more indirection and an actual method call (to a method that most sources do not seem to encourage).

One more thing is that I want to be able to call a switch(type), so that might also limit the possible solutions.

Anyhow, I'm starting to get the idea that there must be a much better solution to this whole problem. Any suggestions?

like image 559
jbeck Avatar asked Jan 03 '12 04:01

jbeck


People also ask

Is Java enum comparable?

Enum constants are only comparable to other enum constants of the same enum type. The natural order implemented by this method is the order in which the constants are declared.

How Java enumeration is different from C and C++?

Enums in C/C++ are plain Integers. Enums in Java are objects - they can have methods (with different behavior from one enum instance to the other). Moreoever, the enum class supplies methods which allows iteration over all enum instances and lookup of an enum instance. Save this answer.

What is enum type in Java?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

Is enum compile time?

Enum values or Enum instances are public, static, and final in Java. They are a compile-time constant, which means you can not changes values of Enum instances and further assignment will result in a compile-time error.


2 Answers

"Classic" java always used "static final int ANIMAL_CAT = 0;" in cases like this.

JDK 1.5 introduced "type-safe enums":

http://www.javapractices.com/topic/TopicAction.do?Id=1

You can now do this (a very common practice):

enum Quark {
    /*
    * These are called "enum constants".
    * An enum type has no instances other than those defined by its
    * enum constants. They are implicitly "public static final".
    * Each enum constant corresponds to a call to a constructor.
    * When no args follow an enum constant, then the no-argument constructor
    * is used to create the corresponding object.
    */
    UP,
    DOWN,
    CHARM,
    STRANGE,
    BOTTOM,
    TOP
  }

Or you can do this:

/**
  * Example 2 - adding a constructor to an enum.
  *
  * If no constructor is added, then the usual default constructor
  * is created by the system, and declarations of the
  * enum constants will correspond to calling this default constructor.
  */
  public enum Lepton {
    //each constant implicity calls a constructor :
    ELECTRON(-1, 1.0E-31),
    NEUTRINO(0, 0.0);

    /* 
    * This constructor is private.
    * Legal to declare a non-private constructor, but not legal
    * to use such a constructor outside the enum.
    * Can never use "new" with any enum, even inside the enum 
    * class itself.
    */
    private Lepton(int aCharge, double aMass){
      //cannot call super ctor here
      //calls to "this" ctors allowed
      fCharge = aCharge;
      fMass = aMass;
    }
    final int getCharge() {
      return fCharge;
    }
    final double getMass() {
      return fMass;
    }
    private final int fCharge;
    private final double fMass;
  }

Here's the official documentation:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html

like image 193
paulsm4 Avatar answered Oct 05 '22 23:10

paulsm4


Why not simply this:

public enum Animal {
    CAT(4), RAT(4), BAT(4), CHICKEN(2), ..., ANT(6), SPIDER(8);

    // A simple attribute, like any other java class.
    // Final to ensure it will never change.
    private final int legs;

    // Note that this constructor is private.
    private Animal(int legs) {
        this.legs = legs;
    }

    // A method, like any other class.
    public int getLegs() {
        return legs;
    }
}

To use it:

// How to get all the animals in the enum.
Animal[] animals = Animal.values();

// How to get the number of animals.
int numAnimals = animals.length;

// How to get the number of legs of some animal.
int howManyLegsHaveTheAnt = Animal.ANT.getLegs();
int howManyLegsHaveTheFirstAnimal = animals[0].getLegs();

// How to get the name of a given animal.
String theFirstAnimalName = animals[0].name(); // Will return "CAT".

// How to get the position in the enum of some animal.
int antPositionInTheEnum = Animal.ANT.ordinal();

// How to get an animal given its name.
Animal rat = Enum.valueOf(Animal.class, "RAT");
Animal someAnimal = Enum.valueOf(Animal.class, animalName);
like image 22
Victor Stafusa Avatar answered Oct 05 '22 23:10

Victor Stafusa