Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Necessity of static block in Java

I found that in Java, there is a feature called static block, which includes code that is executed when a class is first loaded (I don't understand what 'loaded' means, does it mean initialized?). Is there any reason to do the initialization bit inside a static block and not in the constructor? I mean, even the constructor does the same thing, do all the necessary stuff when a class is first initialized. is there anything that the static block accomplishes which a constructor can't?

like image 990
SexyBeast Avatar asked Dec 21 '12 17:12

SexyBeast


People also ask

Why do we need static blocks in Java?

The static block is a block of statement inside a Java class that will be executed when a class is first loaded into the JVM. A static block helps to initialize the static data members, just like constructors help to initialize instance members.

What is the point of a static block?

Static block is used for initializing the static variables. This block gets executed when the class is loaded in the memory. A class can have multiple Static blocks, which will execute in the same sequence in which they have been written into the program.

What is need of static and initializer block?

Java 8Object Oriented ProgrammingProgramming. Instance variables are initialized using initialization blocks. However, the static initialization blocks can only initialize the static instance variables. These blocks are only executed once when the class is loaded.


2 Answers

I first want to highlight one thing thing from your question:

the constructor does the same thing, do all the necessary stuff when a class is first initialized

This is incorrect. A constructor does all the initialization necessary when an instance of a class is created. No constructors execute when the class itself is first loaded into memory and initialized (unless an instance of the class happens to be created as part of the class initialization). This confusion (between initializing a class and initializing instances of the class) is probably why you are questioning the utility of static blocks.

If a class has static members that require complex initialization, a static block is the tool to use. Suppose you need a static map of some kind (the purpose is irrelevant here). You can declare it in-line like this:

public static final Map<String, String> initials = new HashMap<String, String>(); 

However, if you want to populate it once, you can't do that with an in-line declaration. For that, you need a static block:

public static final Map<String, String> initials = new HashMap<String, String>(); static {     initials.put("AEN", "Alfred E. Newman");     // etc. } 

If you wanted to be even more protective, you can do this:

public static final Map<String, String> initials; static {     Map<String, String> map = new HashMap<String, String>()     map.put("AEN", "Alfred E. Newman");     // etc.     initials = Collections.unmodifiableMap(map); } 

Note that you cannot initialize initials in-line as an unmodifiable map because then you couldn't populate it! You also cannot do this in a constructor because simply calling one of the modifying methods (put, etc.) will generate an exception.

To be fair, this is not a complete answer to your question. The static block could still be eliminated by using a private static function:

public static final Map<String, String> initials = makeInitials();  private static Map<String, String> makeInitials() {     Map<String, String> map = new HashMap<String, String>()     map.put("AEN", "Alfred E. Newman");     // etc.     return Collections.unmodifiableMap(map); } 

Note, though, that this is not replacing a static block with code in a constructor as you proposed! Also, this won't work if you need to initialize several static fields in an interrelated way.

A case where a static block would be awkward to replace would be a "master" class that needs to initialize several other classes exactly once.

public class Master {     static {         SlaveClass1.init();         SlaveClass2.init(SlaveClass1.someInitializedValue);         // etc.     } } 

Particularly if you don't want to hard-wire any dependence into SlaveClass2 on SlaveClass1, some sort of master code like this is needed. This kind of stuff most definitely does not belong in a constructor.

Note that there is also something called an instance initializer block. It is an anonymous block of code that is run when each instance is created. (The syntax is just like a static block, but without the static keyword.) It is particularly useful for anonymous classes, because they cannot have named constructors. Here's a real-world example. Since (unfathomably) GZIPOutputStream does not have a constructor or any api call with which you can specify a compression level, and the default compression level is none, you need to subclass GZIPOutputStream to get any compression. You can always write an explicit subclass, but it can be more convenient to write an anonymous class:

OutputStream os = . . .; OutputStream gzos = new GZIPOutputStream(os) {     {         // def is an inherited, protected field that does the actual compression         def = new Deflator(9, true); // maximum compression, no ZLIB header     } }; 
like image 163
Ted Hopp Avatar answered Oct 05 '22 10:10

Ted Hopp


Constructor is invoked while creating an instance of the class.

Static block is invoked when a classloader loads this class definition, so that we can initialize static members of this class. We should not be initializing static members from constructor as they are part of class definition not object

like image 37
Subin Sebastian Avatar answered Oct 05 '22 10:10

Subin Sebastian