简体   繁体   中英

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, ie

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. Ie 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".

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. Ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM