Mahendran
Mahendran

Reputation: 2243

Enum requires no recompilation of its clients - How?

From Effective Java

You can add or reorder constants in an enum type without recompiling its client because the fields that export the constants provide a layer of insulation between an enum type and its clients: the constant values are not compiled into the clients as they are in the int enum pattern.

I understood from this link that int enum patterns are compile-time constants. What I want to know is how enum internally works?

Upvotes: 3

Views: 645

Answers (2)

devconsole
devconsole

Reputation: 7915

What's important to understand is that enums are referenced by name.

Let's say we have an enum:

package com.example;

public enum MyEnum {
    ONE, TWO, THREE
}

And a simple test class:

package com.example;

public class EnumTest {
    public static void main(String[] args) {
        System.out.println(MyEnum.TWO);
    }
}

Now let's decompile the test class using the javap command line tool:

javap -verbose -c com/example/EnumTest yields this (truncated for brevity):

Compiled from "EnumTest.java"
...
const #22 = Field   #23.#25;    //  com/example/MyEnum.TWO:Lcom/example/MyEnum;
const #23 = class   #24;    //  com/example/MyEnum
const #24 = Asciz   com/example/MyEnum;
const #25 = NameAndType #26:#27;//  TWO:Lcom/example/MyEnum;
const #26 = Asciz   TWO;
const #27 = Asciz   Lcom/example/MyEnum;;
...

{
public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic   #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   getstatic   #22; //Field com/example/MyEnum.TWO:Lcom/example/MyEnum;
   6:   invokevirtual   #28; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   9:   return
}

Notice that this code references the constant #22 which in turn indirectly references #26 which is the ASCII string "TWO".

So as long as the class name of MyEnum stays the same and the name of the instance TWO is not changed one does not have to recompile class EnumTest.

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691943

enums are not compile-time constants. So their value is not copied by the compile to every class that uses them. That's different from int values, which can be compile time constants.

So if you have a class like

public class Constants {
    public static final int FOO = 1;
}

and have another class

public class Client {
    public static void main(String[] args) {
        System.out.println(Constants.FOO);
    }
}

the class will print 1. Now change the declaration of FOO to

public static final int FOO = 27;

And recompile Constants without recompiling Client. Execute the Client. The printed value will still be 1, because it has been copied by the compiler to the Client class when the Client class was compiled.

There is no way to have this effect using enums. If you store a value as an instance variable of an enum, or if you refer to its ordinal(), you'll always get the right value, even without recompiling the Client class.

Upvotes: 3

Related Questions