1

I did not understand why below code outputs 10 3 times.

enum Enums {
    A, B, C;
    private Enums() {
        System.out.println(10);
    }
}

public class MainClass {
    public static void main(String[] args) {
        Enum en = Enums.B;
    }
}

It outputs as :

10 10 10
ernest_k
  • 44,416
  • 5
  • 53
  • 99

2 Answers2

4

Printing a constant 10 in your custom enum constructor (which you don't actually need here) is likely confusing you (and it isn't particularly meaningful regardless). Instead pass a value in to the constructor and see the reality of your three constant instances being instantiated. Like,

enum Enums {
    A(1), B(2), C(3);
    private Enums(int v) {
        System.out.printf("%s %d%n", this, v);
    }
}

Which will now output

A 1
B 2
C 3

Corresponding to A, B and C. You might also consider (in main)

System.out.println(Arrays.toString(Enums.values()));

Which yields

[A, B, C]
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
0

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.

NPras
  • 3,135
  • 15
  • 29