Tuesday, June 10, 2008

Forward Referencing

The following notes are taken from Java Language Specification in reference to forward referencing of variables.

The declaration of a member needs to appear 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:
1. The usage occurs in an instance (respectively static) variable initializer of C
or in an instance (respectively static) initializer of C.
2. The usage is not on the left hand side of an assignment.
3. C is the innermost class or interface enclosing the usage.
Example where it needs to be taken care of

public class ForwardReference
{
int j = i;
int i = 10;
}
Here in this example all the above three conditions are met because i is used in the instance variable initializer, i is not on the left hand side of the assignment and the usage of i belongs to the ForwardRef which is the innermost class holding the variable i.

Examples where it need not be taken care of:

Example1:
public class ForwardRef
{
int j;

ForwardReference()
{
j = i;
}

int i = 5;
}

Here the usage is in the constructor and not in instance varialble initializer or instance initializer so the first rule is violated.

Example2:
public class ForwardReference
{
{
i = 9;
}
int i = 8;
}
Here second rule specified in JLS is violated, so we need not worry about it appearing before it is defined. We should be worried if i is used on the right hand side of the assignment.

Example3:
public class ForwardReference
{
class InnerForwardRef
{
int j = i;
}

int i = 5;
}
Here the usage of i is in a inner class so the third rule is violated, so the compiler will not create a problem for this.

Now we come to a very strange example where forward referencing is allowed..
public class X
{
private static int x = getValue();
private static int y = 5;

private static int getValue()
{
return y;
}
public static void main(String args [])
{
System.out.print(x);
}
}

The code above prints..zero which is quite weird in fact. Here the compiler is tricked making it think that it is a valid forward reference.

No comments: