Java: what is static{}?
Can someone explain me what the following is?
public class Stuff
{
static
{
try
{
Class.forName("com.mysql.jdbc.Driver");
}
catch ( ClassNotFoun开发者_JAVA百科dException exception )
{
log.error( "ClassNotFoundException " + exception.getMessage( ) );
}
...
}
What does this static { ...} do?
I know about static variables from C++, but is that a static block or something?
When is this stuff going to get executed?
The static block is called a class static initializer - it gets run the first time the class is loaded (and it's the only time it's run [footnote]).
The purpose of that particular block is to check if the MySQL driver is on the classpath (and throw/log error if it's not).
[footnote] The static block run once per classloader that loads the class (so if you had multiple class loaders that are distinct from each other (e.g. doesn't delegate for example), it will be executed once each.
The primary use of static initializers blocks are to do various bits of initialization that may not be appropriate inside a constructor such that taken together the constructor and initializers put the newly created object into a state that is completely consistent for use.
In contrast to constructors, for example, static initializers aren't inherited and are only executed once when the class is loaded and initialized by the JRE. In the example above, the class variable foo will have the value 998877 once initialization is complete.
Note also that static initializers are executed in the order in which they appear textually in the source file. Also, there are a number of restrictions on what you can't do inside one of these blocks such as no use of checked exceptions, no use of the return statement or the this and super keywords.
I want to add that static variables and static initializers are executed in order of appearance at the time of class loading. So, if your static initializer relies on some static variable, it must be initialized before the particular static block, e.g.
final static String JDBC_DRIVER = getJdbcDriver( );
static
{
try
{
Class.forName(JDBC_DRIVER);
}
catch ( ClassNotFoundException exception )
{
log.error( "ClassNotFoundException " + exception.getMessage( ) );
}
}
In this example getJdbcDriver
will get executed before static initializer. Also, there may be more than 1 static initializer in the class. Once again they are executed in order of appearance.
I also want to mention the existence of instance initializers here, as they do come as surprise when seen for the first time. They look like a code block inside the class body, like this.
class MyClass
{
final int intVar;
{
intVar = 1;
}
}
In general case their use is somewhat unnecessary, because of the constructor, but they are useful in implementing Java's version of closures.
The static initializer block get executed whenever the class is to be loaded for the first time. That can happen if something at higher level is doing a Class#forName("yourpackage.YourClass")
or a new YourClass()
on the class in question for the first time.
By a coincidence, the decent JDBC drivers also have something similar inside. They namely registers themselves in the DriverManager
using a static initializer block:
static {
DriverManager.registerDriver(new ThisDriver());
}
so that whenever you do a Class.forName("somepackage.ThisDriver")
, you will effectively register the driver in the DriverManager
so that you can get a connection from it afterwards.
In addition to all above , there is a minute difference in using class constructor and class initializer. Constructor as we know that will be usually used to initialized the objects and if we have static variables then static block is usually used in order to initialize them when the class will be loaded.
When we have static variables and static block then static variables initialized first and then the block.
When class is first loaded, static block initializes before the class constructor.
static initialization block
is a normal block of code
it is enclosed in braces { }
it is preceded by the static keyword
class Foo { static { // initialization code goes here: doSomething(); } }
class can have any number of static initialization blocks
they can appear anywhere in the class body
they are called in the order of apperence in the code
There is an alternative to static initialization blocks:
- write a private static method
- and assign it to the static class variable
The advantage of this approach is that the static method can be invoked later to reinitialize the class variable.
class Foo {
public static int myVar = initializeClassVariable();
private static int initializeClassVariable() {
// initialization code goes here:
int v = 255;
return v;
}
}
精彩评论