What Is It?
- A block of code ‘{ }’ that runs only one time, and it is run the first time the Constructor or the main() method for that class is called (Sun calls this ‘when the class is initialized‘)
How Does It Work?
- Just declare a static { } block inside your Java class and throw some code in it
- No return statement
- No access to this or super
- Can throw Unchecked Exceptions only
What Can It Be Used For?
- Loading drivers and other items into the namespace. (For example ‘Class.forName(“com.mysql.jdbc.Driver”)’)
- Initialize your complex static members once (possibly for singletons/etc)
- Logging
- Creating/parsing prepared SQL statements
Time to Play
I have created 2 simple classes to play around with the static initializer class: Loader and Test:
class Loader {
static final String theName = "The Loader";
static {
System.out.println("Loader.static");
}
Loader() {
System.out.println("Loader.Loader()");
}
}
class Test {
static {
System.out.println( "Test.static");
}
Test() {
System.out.println( "Test.Test()");
}
public static void main( String [] args ) {
System.out.println( "Test.main");
Test t = new Test();
System.exit(0);
}
}
If we compile and run Test the output we see is:
Test.static
Test.main
Test.Test()
So we see that static block code is called before the main method is executed. Now, let’s define a Loader variable in the constructor and print out ‘Loader.name’.
class Test {
static {
System.out.println( "Test.static");
}
Test() {
System.out.println( "Test.Test()");
// Define a loader and print out the static name
Loader l;
System.out.println( Loader.theName );
}
public static void main( String [] args ) {
System.out.println( "Test.main");
Test t = new Test();
System.exit(0);
}
}
When we compile Test and run it, we now see this:
Test.static
Test.main
Test.Test()
The Loader
So, we can see that neither defining a class nor accessing static class members constitutes “initializing” a class (which would call the static block).
Hmm, ok well lets initialize a few instances of a Loader instead:
class Test {
static {
System.out.println( "Test.static");
}
Test() {
System.out.println( "Test.Test()");
// Make a few Loaders
Loader l1 = new Loader();
Loader l2 = new Loader();
Loader l3 = new Loader();
}
public static void main( String [] args ) {
System.out.println( "Test.main");
Test t = new Test();
System.exit(0);
}
}
Now we compile and execute and we get the expected output:
Test.static
Test.main
Test.Test()
Loader.static
Loader.Loader()
Loader.Loader()
Loader.Loader()
The static block was called only once before the first time the constructor was called.
Well, What About Inheritance?
Let’s try it; we’ll have Test inherit from Loader.
class Test extends Loader {
static {
System.out.println( "Test.static");
}
Test() {
System.out.println( "Test.Test()");
}
public static void main( String [] args ) {
System.out.println( "Test.main");
Test t = new Test();
System.exit(0);
}
}
Now if we compile and run Test we get the output:
Loader.static
Test.static
Test.main
Loader.Loader()
Test.Test()
Interesting, the static blocks get loaded first as usual, but the Loader class had it’s static block called first, which makes sense.
Static initializer blocks: interesting stuff.
Brilliant. Just what I needed. Saved me the time of figuring this out myself.
Unfortunately SOMETHING IS WRONG HERE. Your proposition
“So, we can see that neither defining a class nor accessing static class members constitutes “initializing” a class (which would call the static block).”
is not true. If you ACCESS A STATIC FIELD before making an instance, INITIALIZER IS INVOKED yust after an initialization in declarations.
@beavis42 Hmm. What version of Java are you using? I just compiled the 2 classes again (1.4 and 1.6 for bot Test and Loader) where Test prints
Loader.theName(thereby invoking it); however, nothing else gets printed from Loader, so I would still venture to say that accessing static members does not invoke the static block. If it did, I would have expected to see “Loader.static” printed, but it’s not.I think the confusion here is that accessing a static member variable WILL NOT cause the static block to be invoked. However, calling a static member FUNCTION will cause it to be invoked – I just checked.
engfer, thanks for helping me figure this out.
Hey, Stingray, that’s exactly the information I wanted. I often want to initialize static collection members and that’s exactly how I have to do it. Thanks!
Here’s my test code:
public class Constants {
private static final Set validValues;
static {
validValues = new HashSet();
validValues.add(“value1″);
validValues.add(“value2″);
}
public static Set getValidValues() {
return validValues;
}
}
public class Test {
public static void main(String[] args) {
System.out.println(“Valid values: ” Constants.getValidValues());
}
}
And when I run Test:
Valid values: [value1, value2]
Hi, i tried following example, in this example i tried to access static variables of one class from another class which have main method, in this case also first class static block is executing. and i am using java 1.6 only
Program:
=======
class StatTest {
static int statVariable = 1;
static {
System.out.println(“Static block of StatTest method”);
}
public StatTest() {
System.out.println(“Constructory of StatTest”);
}
}
public class StatTest1 {
static {
System.out.println(“Static block of StatTest1″);
StatTest.statVariable=5;
}
public static void main(String []args) {
System.out.println(“StatTest2 main method”);
}
}
and Output is:
Static block of StatTest1
Static block of StatTest method
StatTest2 main method
@all: Let me tell you what I found with 1.6.0_21:
The static initializer (e.g. Loader.static, StatTest.static) is not invoked if the accessed variable (e.g. theName, statVariable) is a static _final of a primitive or of type String_. But, it is invoked with a variable of type Object, also if it is initialized with a String. WTF?!?
JLS 2.0, 12.4.1 When Initialization Occurs, 4th list item (http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#57946) which leads to 15.28 Constant Expression (http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5313) has the explanation.