I know how a static init block works.
Can anyone please tell me some typical uses of it.
views:
239answers:
6Just try to avoid use of static initialization block. Instead you can use private static initialization functions which will make your code more clean.
I will refer @Bozho examples.
Do not
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
Use
public static Configuration configuration = createConfiguration();
or
public static Configuration configuration = YourConfiguration.create();
When you want to initialize one or more static variables in one place
It is useful, because you can apply exception handling, which is not possible with the in-line initialization.
For example:
public static ImageIcon defaultIcon = ImageIO.read(..);
can be initialized with
public static ImageIcon defaultIcon;
static {
try {
defaultIcon = ImageIO.read(..);
} catch (IOException ex){
System.out.println("No default icon available");
}
}
Another application is complex initialization. For example, if an item requires more than one line of code to be initialized. Let's say you have a configuration:
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
A third usage is to initialize some external API infrastructure. One example from my current project:
static {
org.apache.xml.security.Init.init();
}
But, as Mykola Golubyev noted, static initialization blocks make code less readable, so use them with caution. static methods do the same thing more transparently.
- Initializing a collection static field, like Map, List, Set, etc
- Initializing setter-based object which is also static
They're often used in conjunction with JNI code to ensure that the required native library is loaded:
class MyJniConnection {
public static native void myJniCall();
static {
System.load("native.dll");
}
}
They can be used to create a DSL, as JMock does. For instance, to set an expectation that a user will be saved to the database:
Mockery context = new Mockery();
final Database database = context.mock(Database.class);
...
context.checking(new Expectations() {{
oneOf(database).save(user);
}});
// Rest of the test
JDBC Driver Is a Popular Example
Why do you need Class.forName()
to load a driver into memory. The answer is simple. As stipulated in the JDBC specs, all JDBC Driver
have a static block to register themselves with DriverManager
as soon as the Driver
class is loaded. Something like this:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
So, when you write (for example with the MySQL driver here):
Class.forName("org.gjt.mm.mysql.Driver");
The classloader attempts to load and link the org.gjt.mm.mysql.Driver
class and, if successful, the static initialization block gets executed and the Driver
registers itself with the DriverManager
.