The Artima Developer Community
Sponsored Link

Object Initialization in Java
Object Initialization in the Java Language and Virtual Machine
by Bill Venners
First Published in JavaWorld, February 1998

<<  Page 5 of 8  >>

Advertisement

Initializers
Besides providing constructors, Java offers one other way for you to assign an initial value to instance variables: initializers. As mentioned previously, the two kinds of initializers in Java are instance variable initializers and instance initializers.

Instance variable initializers
In a constructor, you have the freedom to write as much code as needed to calculate an initial value. In an instance variable initializer, you have only an equals sign and one expression. For example, if you wanted to always start coffee cups out with 355 milliliters of fresh brewed coffee in them, you could initialize innerCoffee with a constructor:

// In source packet in file init/ex9/CoffeeCup.java
class CoffeeCup {

    private int innerCoffee;

    public CoffeeCup() {
        innerCoffee = 355;
    }
    // ...
}

Alternatively, you could initialize innerCoffee with an instance variable initializer:

// In source packet in file init/ex10/CoffeeCup.java
class CoffeeCup {
    private int innerCoffee = 355; // "= 355" is an initializer
    // no constructor here
    // ...
}

The right-hand side of the equals sign in an initializer can be any expression that evaluates to the type of the instance variable.

Instance initializers
Java 1.1 introduced the instance initializer, which is also called the instance initialization block. Here is the same CoffeeCup class with its innerCoffee variable initialized by an instance initializer:

// In source packet in file init/ex19/CoffeeCup.java
class CoffeeCup {
    private int innerCoffee;

    // The following block is an instance initializer
    {
        innerCoffee = 355;
    }
    // no constructor here
    // ...
}

This manner of initializing innerCoffee yields the same result as the previous two examples: innerCoffee is initialized to 355.

Instance initializers are a useful alternative to instance variable initializers whenever: (1) initializer code must catch exceptions, or (2) perform fancy calculations that can't be expressed with an instance variable initializer. You could, of course, always write such code in constructors. But in a class that had multiple constructors, you would have to repeat the code in each constructor. With an instance initializer, you can just write the code once, and it will be executed no matter what constructor is used to create the object. Instance initializers are also useful in anonymous inner classes, which can't declare any constructors at all.

The code inside an instance initializer may not return. Except in the case of anonymous inner classes, an instance initializer may throw checked exceptions only if the checked exceptions are explicitly declared in the throws clause of every constructor in the class. Instance initializers in anonymous inner classes, on the other hand, can throw any exception.

Initializers can't make forward references
When you write an initializer (either an instance variable initializer or instance initializer), you must be sure not to refer to any instance variables declared textually after the variable being initialized. In other words, you can't make a forward reference from an initializer. If you disobey this rule, the compiler will give you an error message and refuse to generate a class file. When an object is created, initializers are executed in textual order -- their order of appearance in the source code. This rule helps prevent initializers from using instance variables that have yet to be properly initialized.

For example, here is a virtual cafe class that has four chairs for every table:

// In source packet in file init/ex11/VirtualCafe.java
class VirtualCafe {
    private int tablesCount = 20;
    private int chairsCount = 4 * tablesCount;
    //...
}

These initializers work fine. The chairsCount initializer, = 4 * tablesCount, refers to an instance variable declared textually before it, so the compiler is happy. Because initializers are executed in textual order, tablesCount is already initialized to 20 by the time chairsCount's initializer multiplies it by four. Thus, chairsCount is initialized to 80.

If you were able to use instance variables declared textually later, you could end up with unexpected behavior:

// In source packet in file init/ex12/VirtualCafe.java
// THIS WON'T COMPILE, BUT AS A THOUGHT EXPERIMENT,
// IMAGINE IT WERE POSSIBLE
class VirtualCafe {
    private int chairsCount = 4 * tablesCount;
    private int tablesCount = 20;
    //...
}

If the above declaration were possible, chairsCount's initializer would use tablesCount before tablesCount were assigned a value of 20. At that point, the tablesCount variable would have its default initial value of zero. Hence, this code would initialize chairsCount to four times zero. If you do the math, you will discover that, in this case, chairsCount does not initialize to 80.

Getting around the forward reference rule
Although this kind of forward referencing is disallowed by the compiler in an attempt to help programmers avoid just the above kind of mistake, you can't let down your guard completely. There is still a way you could inadvertently (or purposefully) circumvent the compiler's preventative restrictions:

// In source packet in file init/ex13/VirtualCafe.java
class VirtualCafe {

    private int chairsCount = initChairsCount();
    private int tablesCount = 20;

    private int initChairsCount() {
        return tablesCount * 4;
    }
    //...
}

The above code compiles fine, and has the same result as the previous thought experiment. Here chairsCount's initializer sneakily invokes a method that uses tablesCount before its initializer has been executed. When initChairsCount() calculates tablesCount * 4, tablesCount is still at its default initial value of zero. As a result, initChairsCount() returns zero, and chairsCount is initialized to zero.

<<  Page 5 of 8  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us