Filip Allberg - 11 months ago 46
Java Question

# Java enum evaluations at compile/run-time

When does enum value constructors evaluate? At compile-time or
during program execution?

In fact, my specific case might be even more nuanced than this so
I will expand on the question.

I have a class,

class Instruction


which has a
private enum

private enum InstructionModel


where
InstructionModel
serves as archetypal examples for
instructions. A bare-bones view would be

private enum InstructionModel {
ADD("add $t1,$t2, $t3", 0x014b4820, // Other params ), ; // Some stuff InstructionModel(String example, int sameExample, // Other params ) { // Some other stuff }  Now, the enclosing class ( Instruction ) can create instances of itself from both Strings and numbers, i.e. class Instruction { Instruction fromNumber(int number) { // ... } Instruction fromString(String mnemonic) { // ... } private enum InstructionModel { ... } }  So, Instruction foo = Instruction.fromNumber(0x014b4820); Instruction bar = Instruction.fromString("add$t1, $t2,$t3");
assert(foo.equals(bar));


Now, I could open up the
Instruction
API, so that I could from my
unit tests access the examples encoded into the
InstructionModel
.

But: (assuming my understanding is correct) since an enum
constructor is only ever executed once, I could let the value
constructor verify that the String example yields the
numerical representation and vice versa.

Although, I do not want to do this unless it is simply a compile-time
cost. I.e. could I have

InstructionModel(String example, int sameExample, // Other params
) {

Instruction foo = Instruction.fromNumber(0x014b4820);
Instruction bar = Instruction.fromString("add $t1,$t2, $t3"); assert(foo.equals(bar)); // Some other stuff }  without it affecting the end-user? # Note In this context the following operation is crucial Instruction foo = Instruction.fromNumber(0x014b4820); Instruction bar = Instruction.fromString("add$t1, $t2,$t3");
assert(foo.equals(bar));


as the
InstructionModel
is not sufficient to ascertain whether two
instances are equal.

# Rationale

For those that question the why my reasoning is this:

In comparison with plain JUnit tests, where we'd have to
either encode the knowledge that

"add $t1,$t2, $t3" <-> 0x014b4820 or make the InstructionModel class publicly accessible to access the examples (or access the examples through methods in the enclosing class) it felt prudent to let the constructor evaluate that the proper model is instantiated for a corresponding number. Subsequently, the code will not does not compile if the Instruction constructors are "wrong". Answer Source Constructors evaluate at run-time. This means that the following snippet, InstructionModel(String example, int sameExample, // Other params ) { Instruction foo = Instruction.fromNumber(0x014b4820); Instruction bar = Instruction.fromString("add$t1, $t2,$t3");
assert(foo.equals(bar));

// Some other stuff
}


is evaluated at run-time. It does not matter that it is an enum-constructor. Hence, it is only when the constructor is used that it is evaluated.

Although, I do not want to do this unless it is simply a compile-time cost. I.e. could I have

InstructionModel(String example, int sameExample, // Other params
) {

Instruction foo = Instruction.fromNumber(0x014b4820);
Instruction bar = Instruction.fromString("add $t1,$t2, \$t3");
assert(foo.equals(bar));

// Some other stuff
}


without it affecting the end-user?

No.