Does creating a reference to an object of a class cause the class to be loaded ? Static variables are initialized when the class is loaded, so considering the following code
Yes. Static initializers are called when a class method is called or an instance is instantiated.
From your example you can do one of the following:
public static void main(String[] args) {
A a = new A();
}
public static void main(String[] args) {
int f = A.f();
}
It’s a common mistake to treat loading and initialization of a class as being the same thing.
The Java Language Specification differentiates between
Loading
Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a Java compiler, and constructing, from that binary form, a
Class
object to represent the class or interface.
Linking
Linking is the process of taking a binary form of a class or interface type and combining it into the run-time state of the Java Virtual Machine, so that it can be executed. A class or interface type is always loaded before it is linked.
Three different activities are involved in linking: verification, preparation, and resolution of symbolic references.
Initialization
Initialization of a class consists of executing its
static
initializers and the initializers for static fields (class variables) declared in the class.
Initialization of an interface consists of executing the initializers for fields (constants) declared in the interface.
For most cases, the exact time of loading and linking doesn’t matter, so it’s no problem that the specification provides some freedom to JVM implementations regarding the exact time. Only in the erroneous case, e.g. when a class is absent or there are incompatibilities (linkage or verify errors), JVM specific differences can show up, regarding the exact time when the associated Error
is thrown.
So what your question is aiming at, is not loading, but initialization as you are looking at the side effect produced by the execution of the static
class intializer.
The time of initialization is precisely defined:
§12.4.1. When Initialization Occurs
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
T
is a class and an instance ofT
is created.- A
static
method declared byT
is invoked.- A
static
field declared byT
is assigned.- A
static
field declared byT
is used and the field is not a constant variable (§4.12.4).T
is a top level class (§7.6) and anassert
statement (§14.10) lexically nested withinT
(§8.1.3) is executed.When a class is initialized, its superclasses are initialized (if they have not been previously initialized), as well as any superinterfaces (§8.1.5) that declare any default methods (§9.4.3) (if they have not been previously initialized). Initialization of an interface does not, of itself, cause initialization of any of its superinterfaces.
So from the specification, you can draw the conclusion that the mere presence of a local variable will never trigger an initialization. When assigning a non-null
value to a variable of a reference type, there must have been a preceding instantiation of that type that already triggered its initialization. An unused local variable, however, has no impact.
When it comes to loading rather than initialization, there can be subtle differences, as shown is this scenario.