Filip Allberg Filip Allberg - 3 months ago 15
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

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.

Comments