Reputation: 2243
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 anenum
type and its clients: the constant values are not compiled into the clients as they are in theint
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
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
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