Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: moved some text around

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
bgColor#FFcccc
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 MarkupAccording 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
bgColor#ccccff
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);	
  }
}

...