Author Topic:   forward referencing
rahul_mkar
greenhorn
posted May 12, 2000 12:10 AM             
can anybody explain this.

public class AQuestion
{
private int i = j;
private int j = 10;
public static void main(String args[])
{
System.out.println((new AQuestion()).i);
}
}

Answers

Compiler error complaining about access restriction of private variables of AQuestion.
Compiler error complaining about forward referencing.
No error - The output is 0;
No error - The output is 10;

threadscheduler
greenhorn
posted May 12, 2000 01:42 AM             
The comiler complains about a Forward Referencing error and not about the access protection.

This is because JAVAC is a single pass compiler. The moment it comes across the statement int i=j; it flags an compile time error. so further checks on the statement are not done till the present error is removed.

Now if we remove the forward referencing :
public class AQuestion
{
private int j = 10; // no forward referencing
private int i = j;
public static void main(String args[])
{
System.out.println((new AQuestion()).i);
}
}
>>> The program compiles and runs : output is 10

private access modifier restricts access from other classes but we are using the variable i in the same class AQuestion there is now no compile time error.

rahul_mkar
greenhorn
posted May 12, 2000 11:41 PM             
what is the difference between my question above and the question below and why do they give different results.


public class AQuestion
{
private int i = giveMeJ();
private int j = 10;

private int giveMeJ()
{
return j;
}

public static void main(String args[])
{
System.out.println((new AQuestion()).i);
}
}

Answers

1. Compiler error complaining about access restriction of private variables of AQuestion.
2. Compiler error complaining about forward referencing.
3. No Compilation error - The output is 0;
4. No Compilation error - The output is 10;

the answer is 3 for above


[This message has been edited by rahul_mkar (edited May 12, 2000).]

[This message has been edited by rahul_mkar (edited May 13, 2000).]

Prabhu
greenhorn
posted May 13, 2000 07:48 AM             
Rahul,
IMO when you are declaring int i in the second program, you're pointing this to get the value from the result of a method which is OK.

During compile time, it just checks whether that method with appropriate signature is coded or not (Anywhere in the program, not necessarily before the first reference). Since it's coded somewhere(giveMeJ()), it compiles fine.

During runtime, it tries to execute the method and since it could find one to execute, it runs fine and gets the value.

HTH
Prabhu.

maha anna
bartender
posted May 13, 2000 09:21 AM             
rahul_mkar,
Prabhu is correct. To add on to this, at runtime when an object of this class is created, since instance vars are initialized in the SAME SEQUENCE as they are written in the source file, the var i is initialized first, which in turn calls the giveMeJ() fn which in turn returns the instance var j. The important point to note here is when giveMeJ() is called, the instance var j is NOT YET initialized and so all the instance vars have their default values, the default val for 'int' type which is 0 (zero) is returned.

If the ORDER of initialization WOULD have been changed like the foll.

private int j = 10;
private int i = giveMeJ();

then the var i will have value 10.

regds
maha anna

rahul_mkar
greenhorn
posted May 13, 2000 11:19 PM             
hi,
i would like to know

1) what is the sequence of variable creation, is it static variables first and then instance variables or vice versa
for example
class x{
static int i=5;
int z=3;

}
would i be created first and then z
or
z first and then i or

both at almost the same time;


2)if all variables created first and then initialized as the written sequence then in my first example

"private int i = j; private int j = 10; comiler complains about a Forward Referencing error"

in the above case variables i and j should have been initialized to 0 and then when it comes to the first statement ie "private int i=j" then i should have been assigned 0 and then in the next statement it should have been assigned 10. However this does not happen.


please clarify especially on how the two questions give different results.

maha anna
bartender
posted May 14, 2000 04:05 AM             
rahul_mkar,

for your first request
-----------------------------

static init is done first (when the class is loaded into memory itself), then comes the instance init (done when an object is created from this class).
For example when you access a class's static method, the class is loaded into memory and so ONLY the static floatin blocks, static (class) vars are initialized an written in the same order in the source file. NO instance init done.

At the same time when you do new ThisClass() then if the class is not already in memory, then it is loaded and both static and instance inits are done. Otherwise if it was already loaded before then only the instance init are done and the correcponding constructor is called.

So in your code the static var i is initilized first and then z is initialized. I wrote this sample prog. for you. Play with this. It WILL DEFINITELY make you think./confuse/....clear at the end

************************************************************
output


stat block test1 called
------0
stat block test2 called
------10
stat block test3 called
instance block test1 called
Constructor test1() called
instance block test2 called
Constructor test2() called
instance block test3 called
Constructor test3() called

 
class test1 {

static int stat11 =10;
static {
System.out.println("stat block test1 called");
}

int inst11 =20;
{
System.out.println("instance block test1 called");
}

test1() {

System.out.println("Constructor test1() called");
}

}
class test2 extends test1 {
static int stat21 =10;
static {
System.out.println("------"+test3.stat31);
System.out.println("stat block test2 called");
}

int inst21 =20;
{
System.out.println("instance block test2 called");
}

test2() {

System.out.println("Constructor test2() called");
}
public static void main(String[] args) {
new test2();
}
}

class test3 extends test2 {
static int stat31 =10;
static {
System.out.println("------"+test3.stat31);
System.out.println("stat block test3 called");
}

int inst31 =30;
{
System.out.println("instance block test3 called");
}

test3() {

System.out.println("Constructor test3() called");
}
public static void main(String[] args) {
new test3();
}
}


*********************************************************

ORDER OF EXECUTION

1. - static initialization for test1 done...
(init occurs in the same order as written in source.Both static vars and static blocks are initialized)
2. - static initialization for test2 done...
(init occurs in the same order as written in source.Both static vars and static blocks are initialized)
3. - static initialization for test3 done...
(init occurs in the same order as written in source.Both static vars and static blocks are initialized)


4. - instance initialization for test1 done...
(init occurs in the same order as written in source.Both instance vars and instance blocks are initialized )
5. - Constructor test1() called


6. - instance initialization for test2 done...
(init occurs in the same order as written in source.Both instance vars and instance blocks are initialized )
7. - Constructor test2() called


8. - instance initialization for test3 done...
(init occurs in the same order as written in source.Both instance vars and instance blocks are initialized )
9. - Constructor test3() called

*********************************************************

for your 2nd request
--------------------------
At compile time you can't refer to a var as such if it not known before this referencing. THis is the rule. Because the var is not yet known. But when you call a fn what the compiler actually it basically creates code to which implementaion of the fn to execute like that. At run time when you call a method, and if it refers to a class/instance var, if it is not yet initialized , the default values are taken for granted. The important point to note here is eventhough the class/instance var are given default valuse you can't forward reference through the ref as such. Because the scope of a var and a method is differnet. A var's scope is at the place where it is declared and below the declaration point. But a method's scope is anywhere in the containing class. THis is the difference And also this is the reason why your programs behaves differently. Eventhough the link which I given below doesn't explicity elaborate this, we have link what is said in the 'scope' section and this context and come to a conclusion/reason.

regds
maha anna
From JLS


The static initializers and class variable initializers are executed in textual order and may not

refer to class variables declared in the class whose declarations appear textually after the use,
even though these class variables are in scope. This restriction is designed to catch, at
compile time, circular or otherwise malformed initializations. Thus, both:
class Z {
static int i = j + 2;
static int j = 4;
}
and:
class Z {
static { i = j + 2; }
static int i, j;
static { j = 4; }
}
result in compile-time errors.
Accesses to class variables by methods are not checked in this way
class Z {
static int peek() { return j; }
static int i = peek();
static int j = 1;
}
class Test {
public static void main(String[] args) {
System.out.println(Z.i);
}
}
produces the output:
0

Please refer to JLS especially this section

regds
maha anna

[This message has been edited by maha anna (edited May 14, 2000).]

prpanicker@yahoo.com
unregistered
posted May 14, 2000 05:47 AM           
quote:
Originally posted by rahul_mkar:
hi,
i would like to know

1) what is the sequence of variable creation, is it static variables first and then instance variables or vice versa
for example
class x{
static int i=5;
int z=3;

}
would i be created first and then z
or
z first and then i or

both at almost the same time;

class MBT{
MBT(int i){
System.out.println(i);
}
}
public class Stat {
static MBT m1=new MBT(1);
MBT m2=new MBT(2);

static MBT m3=new MBT(3);
public static void main(String[] s){
Stat st=new Stat();

}
}
Try out this program you have your answer.


2)if all variables created first and then initialized as the written sequence then in my first example

"private int i = j; private int j = 10; comiler complains about a Forward Referencing error"

in the above case variables i and j should have been initialized to 0 and then when it comes to the first statement ie "private int i=j" then i should have been assigned 0 and then in the next statement it should have been assigned 10. However this does not happen.


please clarify especially on how the two questions give different results.


|