In studying for the Java certification test I learned that static initialization blocks run once when the class is loaded, in order of appearance within the source code, that instance initialization blocks run each time an instance is created, and that code in constructors runs each time an instance is created after that. To test that I created a class with some static and instance init blocks and a contructor with print stuff. Everything worked as expected -- except I thought "loaded" meant just at runtime, but I guess it happens when the first instance is created, since I don't get any output at all unless I create at least 1 instance of the class. Then I tried the same with an enum and the order was all off. First, the initialization blocks run one time for each value the enum has when the enum is first referenced in code, secondly -- the init blocks marked static run after what I assumed were instance init blocks! This is the opposite of what I expected. Here is a breakdown of my questions.
Thanks! This is very confusing to me.
public class EnumInit {
public static void main(String[] args) {
System.out.println(Color.RED.toString() + " Main");
MyInit myInit = new MyInit();
System.out.println(Color.BLUE.toString() + " Main");
MyInit mySecondInit = new MyInit();
}
}
enum Color {
RED, BLUE, GREEN;
String instanceVar = "Enum Instance Variable Text";
static { System.out.println("Enum Static init block 1"); }
{ System.out.println("Enum Instance init block 1"); }
static { System.out.println("Enum Static static init block 2"); }
Color() {
System.out.println(instanceVar);
System.out.println("Enum String Literal");
}
{ System.out.println("Enum Instance init block 2"); }
}
class MyInit {
String instanceVar = "Class Instance Variable Text";
static { System.out.println("Class Static init block 1"); }
{ System.out.println("Class Instance init block 1"); }
static { System.out.println("Class Static static init block 2"); }
MyInit() {
System.out.println(instanceVar);
System.out.println("Class String Literal");
}
{ System.out.println("Class Instance init block 2"); }
}
Static blocks can be used to initialize static variables or to call a static method. However, an instance block is executed every time an instance of the class is created, and it can be used to initialize the instance data members.
An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden). An enum cannot be used to create objects, and it cannot extend other classes (but it can implement interfaces).
Enums limit you to the required set of inputs whereas even if you use constant strings you still can use other String not part of your logic. This helps you to not make a mistake, to enter something out of the domain, while entering data and also improves the program readability.
Java Enums provide many features that integer constants cannot. Enums can be considered as final classes with a fixed number of instances. Enums can implement interfaces but cannot extend another class. While implementing the strategy pattern, we can use this feature of Enums.
The Java Language Specification says this about enum
constants
In addition to the members that an enum type E inherits from Enum, for each declared enum constant with the name n, the enum type has an implicitly declared public static final field named n of type E. These fields are considered to be declared in the same order as the corresponding enum constants, before any static fields explicitly declared in the enum type. Each such field is initialized to the enum constant that corresponds to it.
So
enum Color {
RED, BLUE, GREEN;
...
}
is actually
public static final Color RED = new Color();
public static final Color BLUE = new Color();
public static final Color GREEN = new Color();
which will get evaluated before the static
blocks you have.
Why do the init blocks marked static run last in an enum?
See above.
Can an enum have instance init blocks?
Yes, compile your code and you will see.
Why do the blocks I thought were instance init blocks run only once when the enum is loaded and not each time a new enum value is referenced?
Enum constants are created (instantiated) once the enum type is initialized. You don't create a new enum
any time you do
Color color = Color.RED;
You are just referencing an already created, existing object.
Class static init blocks run when a class is "loaded". What does loaded mean? Does it occur just once when an object is instantiated in the class?
When a class is referenced in the JVM for the first time, it is loaded by the ClassLoader
and initialized. Read more about it here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With