To understand why you're seeing the constructor called multiple times, we'll have a look at what happens behind the screen.
Starting with a simple Enums.java
:
enum Enums { A, B; }
We'll compile, then immediately decompile to see what Java actually does with it internally:
javac Enums.java && javap -c Enums
which gives the following result (I'll cut a lot for brevity, but keep the important bits):
final class Enums extends java.lang.Enum<Enums> {
public static final Enums A;
public static final Enums B;
...
static {}; //<-- Static initialiser
Code:
//Construct a new object, assign it to A
0: new #4 // class Enums
3: dup
4: ldc #7 // String A
6: iconst_0 // 0
7: invokespecial #8 // Method "<init>":(LString;I)V <-- calls the parent constructor with "string A" and "const 0" above
10: putstatic #9 // Field A:LEnums;
//Construct another, assign it to B
13: new #4 // class Enums
16: dup
17: ldc #10 // String B
19: iconst_1 // 1
20: invokespecial #8 // Method "<init>":(LString;I)V <-- calls the parent constructor with "string B" and "const 1 above"
23: putstatic #11 // Field B:LEnums;
...
45: return
}
What you have there are:
- Two
public static final
fields called A
and B
, and
- A static initialiser, which contains two
new
statements that constructs both A
and B
.
- As all enums are descended from
java.lang.Enum<>
, the two new
calls also invoke the parent's constructor: protected Enum(String name, int ordinal)
to give A
and B
a name and a numeric order.
The static initialiser you see above is the cause of you seeing multiple calls to your println()
, even though you are only using one of the enums. The nature of static initialisers is that it gets called when you first use a class.
And as you can see in the code produced by the compiler, it will immediately construct both A
and B
(and C
in your case), when you attempt to use your enum.