Wiki Markup |
---|
According to the Java Language Specification \[[JLS 2005|AA. Bibliography#JLS 05]\], Section 12.4, "Initialization of Classes and Interfaces" |
Initialization of a class consists of executing its static
initializers and the initializers for static
fields (class variables) declared in the class.
Wiki Markup |
---|
This statement asserts that the presence of a {{static}} field triggers the initialization of a class. However, a static field might depend on the initialization of a class, and might create an initialization cycle. The Java Language Specification also states: (\[[JLS 2005|AA. Bibliography#JLS 05]\], Section 8.3.2.1, "Initializers for Class Variables") |
...at run time, static
variables that are final
and that are initialized with compile-time constant values are initialized first.
...
Noncompliant Code Example
Wiki Markup |
---|
In this noncompliant code example, a recursive attempt is being made to initialize the class, creating an initialization cycle. Because such recursive attempts are ignored by the JVM, the default value of {{deposit}} is {{0}} during the initialization \[[Bloch 2005|AA. Bibliography#Bloch 05]\]. The code tries to calculate the account balance by subtracting the processing fee from the deposited amount, but fails to do so. The {{Cycle}} class object {{c}} is instantiated before the {{deposit}} field gets initialized. |
This noncompliant code example contrives to calculate the account balance by subtracting the processing fee from the deposited amount, but fails to do so. The Cycle
class object c
is instantiated before the deposit
field gets initialized. Code Block |
---|
|
public class Cycle {
private static final Cycle c = new Cycle();
private final int balance;
private static final int deposit = (int) (Math.random() * 100); // Random deposit
public Cycle() {
balance = deposit - 10; // Subtract processing fee
}
public static void main(String[] args) {
System.out.println("The account balance is: " + c.balance);
}
}
|
As a result, the constructor Cycle()
is invoked which computes the balance based on the initial value of deposit
(0) rather than the random value. As a result, the balance always remains -10
. Wiki Markup |
According to the Java Language Specification \[[JLS 2005|AA. Bibliography#JLS 05]\], Section 12.4, "Initialization of Classes and Interfaces"
Initialization of a class consists of executing its static
initializers and the initializers for static
fields (class variables) declared in the class.
Wiki Markup |
---|
This statement asserts that the presence of a {{static}} field triggers the initialization of a class, however, in this example, a recursive attempt is being made to initialize the class already. Because such recursive attempts are ignored by the JVM, the default value of {{deposit}} is {{0}} during the initialization \[[Bloch 2005|AA. Bibliography#Bloch 05]\]. |
Compliant Solution
This compliant solution changes the initialization order of the class Cycle
so that the fields meant to be used in computations get duly initialized without creating any dependency cycles.
Code Block |
---|
|
public class Cycle {
private final int balance;
private static final int deposit = (int) (Math.random() * 100); // Random deposit
private static final Cycle c = new Cycle(); // Inserted after initialization of required fields
public Cycle(){
balance = deposit - 10; // Subtract processing fee
}
public static void main(String[] args) {
System.out.println("The account balance is: " + c.balance);
}
}
|
...