Home > Software engineering >  Java Representation of C Enum
Java Representation of C Enum

Time:06-05

I am porting to Java a bytecode compiler written in C. In the C implementation, the set of operations is represented in an enum:

typedef enum {
  SOME_OP,
  ANOTHER_OP,
  //Etc.
} Operations;

Operations are then mixed with numeric arguments in an array defined as:

uint8_t* opsAndArgs;

For example, opsAndArgs might hold:

{SOME_OP, 42, ANOTHER_OP, 99, 03, DIFFERENT_OP, RANDOM_OP, 14, etc.}

Finally, a function in the C program iterates through opsAndArgs and switches on operators, consuming arguments as appropriate:

int i = 0;

while (i < opsAndArgs.length) {
  switch (opsAndArgs[i] {
    case SOME_OP:
      handleSomeOp(opsAndArgs[i 1]);
      i = i   2; break;
    case ANOTHER_OP:
      handleAnotherOp(opsAndArgs[i 1], opsAndArgs[i 2]);
      i = i   3; break;
    case DIFFERENT_OP:
      handleDifferentOp();
      i = i   1; break;
    Etc.
  }
}

Is there a way I can do the same thing in Java? I.e., create an Enum that I can mix into an array with numeric values, and still have the ability to switch on Enum-defined operators while treating the remaining values as arguments?

It seems like the original program is taking advantage of some feature of C enums such that they are mix-able with uint8_t values.

CodePudding user response:

Unlike in C, an enum in Java is an object. That means that the only way to mix the them with numbers is with a List<Object> or Object[].

Every enum does have an ordinal() value that is an int. These are not compile-time constants though, so you can't use them in switch statements*.

I think that you have some options:

  1. Go for the List<Object> / Object[] solution. If you only perform switching on the operations, you can do this with a combination of instanceof and switch
if (opsAndArgs[i] instanceof Operation operation) { // **
    switch (operation) {
        case SOME_OP: ...
    }
}
  1. Forget the enum and go for a constants class:
final class Operation {
    public static final int SOME_OP = 1;
    // etc

    private Operation() {}
}
  1. Define int constants for each enum constant. Each enum constant must return one of these, and you'll need to have a lookup (static method) on the enum class to find the enum constant based on the int constant. Don't trust on ordinal() as constants because if you change the order of enum constants the ordinal values change as well.

I think the main question you have to ask yourself is: do you need an enum? Or is the constants class good enough? Because that's definitely the easier of the solutions.

* Yet? I'm not fully up-to-speed with the latest changes to switch pattern matching...

** That's syntax finalized in Java 16. In older versions, use opsAndArgs[i] instanceof Operation in combination with a new variable inside the if: Operation operation = (Operation) opsAndArgs[i];

CodePudding user response:

From my point of view:

  • Keep the structure of the C byte code interpreter, else life gets too complicated!

  • opsAndArgs has to be a byte array. We are talking about Java byte code here. Some values have to be interpreted as bytes, some as shorts, ... and the program counter needs to advance in byte-sized steps.

  • Use static final byte for opcodes.

  • Related