Static Block in Java
It's a static initializer. It's executed when the class is loaded (or initialized, to be precise, but you usually don't notice the difference).
It can be thought of as a "class constructor".
Note that there are also instance initializers, which look the same, except that they don't have the static
keyword. Those are run in addition to the code in the constructor when a new instance of the object is created.
Static block and a Normal Block
Static block are executed when classes are loaded where as normal blocks are executed when an instance of the class enclosing the block is created.
Just for the record prior to java 7 static blocks were executed before main() method was searched in the project. But from java 7 main() is first looked up. So you will get an error if you don't have main.So saying I know the static blocks run before main
is a bit ambiguous. main() method is looked up prior to executing static blocks but the main execution will start after the static blocks are handled.
Also non static blocks are executed before the corresponding constructor is invoked.
For example
public class Tester {
{
System.out.println("In some random block");
}
static {
System.out.println("In static block");
}
public Tester() {
System.out.println("Constructor");
}
public static void main(String args[]) {
Tester t = new Tester();
}
}
will print
In static block
In some random block
Constructor
How to execute a static block for multiple times in java
Executing a Static Block can be Achieved by using Custom Class Loader.
ClassReload.java
Class<?> load = ClassLoader.getSystemClassLoader().loadClass("com.Hello");
//Assume Hello class is in "com" package
load.newInstance().toString();
URL[] urls = { load.getProtectionDomain().getCodeSource().getLocation() };
ClassLoader delegateParent = load.getClassLoader().getParent();
try (URLClassLoader cl = new URLClassLoader(urls, delegateParent)) {
Class<?> reloaded = cl.loadClass(load.getName());
reloaded.newInstance().toString();
}
}
}
Refer Oracle Document for URLClassLoader
Can one force execution of the static blocks of all the files in the application?
This is not possible, since the VM will never attempt to load a class that isn't required by the code path traversed on its own. There are some obvious and some obscure reasons why its done that way.
Rule of thumb is: If there is no dependency to a class that is reachable (through code) from the programs entry point, then that class will never be loaded. Although reachable is quite lose, e.g. a reference can be established by just knowing a class' name (e.g. from a configuration file) and accessing that class with e.g. Class.forName().
What you cannot achieve is just dropping a class into the class path and have that class automagically become an additional entry point (which executing any static code without a cause from the main (and only) entry point would classify as).
Difference between the static initializer block and regular static initialization
For your example, there is no difference. But as you can see,
public static String myString = "Hello World!";
can only accept an expression to initialize the variable. However, in a static initializer (JLS 8.7), any number of statements may be executed. E.g. it's possible to do this:
static
{
myString = "Hello";
myString += " ";
myString += "World";
}
For your example, there's obviously no need to do that, but it's possible for the initialization of a variable to take more than an expression, perhaps many statements, so Java made static initializers.
what is the difference between Initializing a static object inside static block and outside?
In your examples mentioned above both the program is doing the same thing. So you can't judge what is difference between initializing static object and static block. Static block will be called only once at the time of loading the class by the JVM. Purpose of static block is to initialize the static variables and calling static methods. Remember one thing,initialize before you use any resources and for that this is one option which wil be called even before calling the constructor of the class. If you have the requirement to initialize the static variables at the time of loading the class or calling the methods at the time of loading the class to initialize something then in that case static block will be helpful. Here is the example of creating the static object and initializing it in static block.
private static List<String> arrList = new ArrayList<>();
static{
arrList.add("Hello");
arrList.add("World!!!");
}
Necessity of static block in Java
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 "coordinator" class that needs to initialize several other classes exactly once, especially awkward if it involves dependency injection.
public class Coordinator {
static {
WorkerClass1.init();
WorkerClass2.init(WorkerClass1.someInitializedValue);
// etc.
}
}
Particularly if you don't want to hard-wire any dependence into WorkerClass2
on WorkerClass1
, some sort of coordinator 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
}
};
What's the C++ idiom equivalent to the Java static block?
You can have static blocks in C++ as well - outside classes.
It turns out we can implement a Java-style static block, albeit outside of a class rather than inside it, i.e. at translation unit scope. The implementation is a bit ugly under the hood, but when used it's quite elegant!
Downloadable version
There's now a GitHub repo for the solution, containing a single header file: static_block.hpp
.
Usage
If you write:
static_block {
std::cout << "Hello static block world!\n";
}
this code will run before your main()
. And you can initialize static variables or do whatever else you like. So you can place such a block in your class' .cpp
implementation file.
Notes:
- You must surround your static block code with curly braces.
- The relative order of execution of static code is not guaranteed in C++.
Implementation
The static block implementation involves a dummy variable initialized statically with a function. Your static block is actually the body of that function. To ensure we don't collide with some other dummy variable (e.g. from another static block - or anywhere else), we need a bit of macro machinery.
#define CONCATENATE(s1, s2) s1##s2
#define EXPAND_THEN_CONCATENATE(s1, s2) CONCATENATE(s1, s2)
#ifdef __COUNTER__
#define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_CONCATENATE(prefix, __COUNTER__)
#else
#define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_CONCATENATE(prefix, __LINE__)
#endif // __COUNTER__
#ifdef _MSC_VER
#define _UNUSED
#else
#define _UNUSED __attribute((unused))
#endif // _MSC_VER
and here is the macro work to put things together:
#define static_block STATIC_BLOCK_IMPL1(UNIQUE_IDENTIFIER(_static_block_))
#define STATIC_BLOCK_IMPL1(prefix) \
STATIC_BLOCK_IMPL2(CONCATENATE(prefix,_fn),CONCATENATE(prefix,_var))
#define STATIC_BLOCK_IMPL2(function_name,var_name) \
static void function_name(); \
static int var_name _UNUSED = (function_name(), 0) ; \
static void function_name()
Notes:
- Some compilers do not support
__COUNTER__
- it's not part of the C++ standard; in those cases the code above uses__LINE__
, which works too. GCC and Clang do support__COUNTER__
. - This is C++98; you don't need any C++11/14/17 constructs. However, it's not valid C, despite not using any classes or methods.
- The
__attribute ((unused))
might be dropped, or replaced with[[unused]]
if you have a C++11 compiler which doesn't like the GCC-style unused extension. - This does not avert or help with the static initialization order fiasco, since while you know your static block will execute before
main()
, you are not guaranteed when exactly that happens relative to other static initializations.
Live Demo
Static Initialization Blocks
The non-static block:
{
// Do Something...
}
Gets called every time an instance of the class is constructed. The static block only gets called once, when the class itself is initialized, no matter how many objects of that type you create.
Example:
public class Test {
static{
System.out.println("Static");
}
{
System.out.println("Non-static block");
}
public static void main(String[] args) {
Test t = new Test();
Test t2 = new Test();
}
}
This prints:
Static
Non-static block
Non-static block
Why static block is not executed
A class's static initialization normally happens immediately before
the first time one of the following events occur:
- an instance of the class is created,
- a static method of the class is invoked,
- a static field of the class is assigned,
- a non-constant static field is used, or [...]
You are currently not doing any of the above.
So, by replacing
Class<?> class1 = A.class;
System.out.println(class1);
with this for example
A object = new A();
will give you your result.
Related Topics
Causes of Getting a Java.Lang.Verifyerror
Why Can't I Do Assignment Outside a Method
How to Parse/Format Dates With Localdatetime - Java 8
How to Format the Day of the Month to Say "11Th", "21St" or "23Rd" (Ordinal Indicator)
Regex For Splitting a String Using Space When Not Surrounded by Single or Double Quotes
Should I Always Use a Parallel Stream When Possible
How Does the "Final" Keyword in Java Work (I Can Still Modify an Object.)
How to Run a Java Program from the Command Line on Windows
Difference Between a Static Method and a Non-Static Method
Convert String to Double in Java
How to Programmatically Determine Operating System in Java
What's the Best Way to Build a String of Delimited Items in Java
Including Jars in Classpath on Commandline (Javac or Apt)
How to Take a Screenshot Using Java and Save It to Some Sort of Image