Continuing Reading Java Language Specification turned to chapter Classes
Now in section Restrictions on the use of Fields during Initialization.
Can we predict the output of this program?
class Z {
int k=j;
static int i = j;
static int j = 4;
}
class ZZ extends Z {
static { i = j + 2; }
static int i, j;
static { j = 4; }
}
public class CircularInitializationsExample {
public static void main(String[] args) {
Z z=new Z();
Z zz=new ZZ();
System.out.println(z.i);
System.out.println(zz.i);
}
}
Well this results in compilation problem as there is circular initialization happening here.As static variables are initialized first hence i and j are in circular dependency which causes a compilation problem.
Also variable j is trying to be referenced before initialization.But this rule wont be applied for instance variables as instance variables are loaded after static variables being loaded.
For Example:
int k=j;
static int j=10;
These restrictions are designed to catch, at compile time, circular or otherwise
malformed initializations.
As JLS States:
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:
The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C is the innermost class or interface enclosing the usage.
A compile-time error occurs if any of the four requirements above are not met.
An Eloborate Example as given in JLS where all the rules are followed.
class ElobarateExample {
static {
x = 100; // ok - assignment
int y = x + 1; // error - read before declaration
int v = x = 3; // ok - x at left hand side of assignment
int z = ElobarateExample.x * 2;
// ok - not accessed via simple name
Object o = new Object(){
void foo(){x++;} // ok - occurs in a different class
{x++;} // ok - occurs in a different class
};
}
{
j = 200; // ok - assignment
j = j + 1; // error - right hand side reads before declaration
int k = j = j + 1;
int n = j = 300; // ok - j at left hand side of assignment
int h = j++; // error - read before declaration
int l = this.j * 3; // ok - not accessed via simple name
Object o = new Object(){
void foo(){j++;} // ok - occurs in a different class
{ j = j + 1;} // ok - occurs in a different class
};
}
int w = x = 3; // ok - x at left hand side of assignment
int p = x; // ok - instance initializers may access static fields
static int u = (new Object(){int bar(){return x;}}).bar();
// ok - occurs in a different class
static int x;
int m = j = 4; // ok - j at left hand side of assignment
int o = (new Object(){int bar(){return j;}}).bar();
// ok - occurs in a different class
int j;
}
Hope this explanation helps.
Tuesday, 25 September 2007
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment