Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do static and instance init blocks in Enums behave differently from those in Classes

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.

  1. Why do the init blocks marked static run last in an enum?
  2. Can an enum have instance init blocks?
  3. 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?
  4. 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?

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"); }  
}
like image 274
paniclater Avatar asked Dec 16 '13 20:12

paniclater


People also ask

What is the difference between static block and instance block?

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.

What is difference between enum and class in Java?

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).

Why enums are better than constants?

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.

How are Java enums more powerful than integer constants How can this capability be used?

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.


1 Answers

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.

like image 195
Sotirios Delimanolis Avatar answered Oct 16 '22 18:10

Sotirios Delimanolis