my dog learned polymorphism*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Initialization Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Initialization" Watch "Initialization" New topic
Author

Initialization

Rana Thakur
Greenhorn

Joined: Feb 26, 2001
Posts: 26
Hi All,
Q1) Consider the code below:
public class test {
static {
int j = fn ();
}
public static void main(String[] args) {
fn();
}
static int fn () {
System.out.println (i);
return 6;
}
static int i =10; //----(1)
}
Output is :: 0, 10
Till now I was of the understanding that the member variables are set to their default values after the static initialization is over. How come the value of i printed out in function fn() displays its default value even before the line (1) is executed??
What am I missing here??

Q2) Given the hierarchy
class base {}
class der extends base {}
Are the following steps of initialization correct?
1.) The static initializer of base class is called.
2.) Then the static initializer of the derived class.
3.) The base class member variables are initialized
4.) The base class constructor is called
5.) The dervied class member variables are initialized
6.) The derived class constructor is called.
When are the base class member variables/ derived class member variables set to their default values?

Thanks in advance

Sivalingam Sivasuthan
Ranch Hand

Joined: Jan 12, 2001
Posts: 75
Q1)
In the static block you are declaring a int variable 'j' and initialising it by calling the method fn which will return 6. In that method you are forward referencing the variable 'i' but the compiler does not detect it. The declaration of ststic variable �i� is after the this static block execution doesn�t mean that it is not extant. It is only initialized to the assigned value after the static block. Thus, when�i� is referenced in the fn() method it will print the un initialized value of �i� which is �0� by default.
Siva.

- Siva<br /> Sun Certified Programmer for the Java™2 Platform
ryan burgdorfer
Ranch Hand

Joined: Jan 24, 2001
Posts: 219
All static init takes place before the main method runs, even though main() is in the middle. In the first static block, i is 0, and j is 6. Then in the second block, i is 10. The execution goes like this:

1. static block: j = 6, 0 is printed
2. static block: i = 10
3. main: 10 is printed

So you can see, the output makes sense.


<UL TYPE=SQUARE><I><LI>Ryan Burgdorfer<BR><LI>Java Acolyte</I></UL>
Rana Thakur
Greenhorn

Joined: Feb 26, 2001
Posts: 26
Thanks a lot guys.
So is it correct to say that even before the first static block is executed, all the variables are are set to their default values??
And similarly in Q2 all the member variables of base class and derived class will be initialized to their default values before the step 1 i.e. the static initializer of base class is called. ??
I remember reading somewhere that the member variables are set to their default values after the static initializer is run. Is it wrong??
Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
Static initializing code is called at class load time. Then initializers for static fields are called. So even if you just declare a "der" (der myDer ; ) and defer the initialization, the static code from the base and the der are called. No instance variables are created or initialized at this point. Static methods are available to be called at this point. Note: if you say Math.sqrt(i) this causes the Math class to load.
When you declare the der the variables for a der are created on the stack
Initializing code and constructors are called when on object is created with the new operator (myDer = new der(); ), with the base class being completely constructed before the der class gets constructed.
Back to your original question; when test was loaded the static block ran and printed 0 (notice that you used i before it was declared - so the compiler ran off and found the i below and created it a bit earlier than it would have normally). Then i was set to 10 during initializing static members outside the blocks. Then main was run calling the method and printing 10, just like you described it should. Just because the initializing code is physically at the end of test does not mean it gets executed last. It executed during initialization.
Member variables are set during non-static initialization and construction, where-ever they are declared or referenced (you can actually use variables in code before you declare them in the file, because the compiler will scan for variables before it attempts to resolve active code).

From the JVM Specification

2.16.4 Initialization
Initialization of a class consists of executing its static initializers (�2.11) and the initializers for static fields (�2.9.2) declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface (�2.13.4).
Before a class is initialized, its superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized.
A class or interface type T will be initialized at its first active use, which occurs if:

T is a class and a method actually declared in T (rather than inherited from a superclass) is invoked.
T is a class and a constructor for class T is invoked.
A nonconstant field declared in T (rather than inherited from a superclass or superinterface) is used or assigned. A constant field is one that is (explicitly or implicitly) both final and static, and that is initialized with the value of a compile-time constant expression. Java specifies that a reference to such a field must be resolved at compile time to a copy of the compile-time constant value, so uses of such field are never active uses.

[This message has been edited by Cindy Glass (edited March 03, 2001).]


"JavaRanch, where the deer and the Certified play" - David O'Meara
ryan burgdorfer
Ranch Hand

Joined: Jan 24, 2001
Posts: 219
Static initializing code is called at class load time. Then initializers for static fields are called. So even if you just declare a "der" (der myDer ; ) and defer the initialization, the static code from the base and the der are called. No instance variables are created or initialized at this point. Static methods are available to be called at this point. Note: if you say Math.sqrt(i) this causes the Math class to load.
When you declare the der the variables for a der are created on the stack

This seems to be a contradiction...
In the last red part, did you mean to say that when you initialize the der its variables are created on the stack?
Dilshad Syed
Greenhorn

Joined: Mar 05, 2001
Posts: 29
These examples beautifully describe and explain the initialization sequence:
Example 1:
Determine the result of attempting to compile and run the following code:
1: class A {
2: public A() {
3: System.out.println("AAA");
4: }
5: {
6: System.out.println("456");
7: }
8: }
9:
10: public class B extends A {
11: B() {
12: this(12);
13: System.out.println("BBB");
14: }
15: B(int x) {
16: System.out.println("CCC");
17: }
18: {
19: System.out.println("123");
20: }
21: public static void main(String[] args) {
22: new B();
23: }
24: }
Answer
Object Construction I
The output is:
456
AAA
123
CCC
BBB
The first statement in any Java constructor will always be one of the following:
A call to another constructor in the same class using the "this();" notation. For example, this(parm1, parm2, parm3);
A call to a constructor in the super class using the "super();" notation. For example, super(parm1, parm2, parm3);
Neither of the above two in which case the compiler invisibly inserts a call to the superclass no-arg constructor as the first statement: super();
From the above three cases it should be clear that if some class B extends another class, A, calling B's constructor will result in one of A's constructors being executed in its entirety before the second statement is B is ever executed.
Once a class' base class constructor has completed executing, any instance initializers defined by the class are executed, in the order in which they are defined. After all instance initializers have executed the constructor body finally executes.
Using the example code above, the following events occur:
B's no-arg constructor is invoked from main().
The B() constructor makes a call to another constructor (B(int)) in its class using the "this()" notation: this(12);.
The B(int) constructor does not call another constructor in the same class nor does it explicitly call a constructor in the base class. Therefore, the compiler invisibly inserts a call to A's no-arg constructor as the first statement in B(int).
The A() constructor does not call another constructor in the same class nor does it explicitly call a constructor in the base class (java.lang.Object). Therefore, the compiler invisibly inserts a call to java.lang.Object's no-arg constructor as the first statement in A().
After java.lang.Object's no-arg constructor returns, all instance initializers in A are then executed. This results in the string "456" being printed.
After A's instance initializer completes the A() constructor body executes, printing the string, "AAA".
Once A's constructor completes control is returned to the B(int) constructor. But before the body of that constructor executes B's instance initializers must be run. This results in the string, "123" being printed.
After B's instance initializer completes, the B(int) constructor body executes, printing the string, "CCC".
Finally, control returns back to B's no-arg constructor which prints, "BBB".

-----------------------------------------------------------------
Example 2:
Determine the result of attempting to compile and run the following code:
1: class A {
2: public int Avar;
3: public A() {
4: System.out.println("AAA");
5: doSomething();
6: }
7: public void doSomething() {
8: Avar = 1111;
9: System.out.println("A.doSomething()");
10: }
11: }
12:
13: public class B extends A {
14: public int Bvar = 2222;
15: public B() {
16: System.out.println("BBB");
17: doSomething();
18: System.out.println("Avar=" + Avar);
19: }
20: public void doSomething() {
21: System.out.println("Bvar=" + Bvar);
22: }
23: public static void main(String[] args) {
24: new B();
25: }
26: }
Answer:
The output is:
AAA
Bvar=0
BBB
Bvar=2222
Avar=0
Answering this question requires that you understand Example 1. In addition, you must observe that when the doSomething() method is invoked from within A's constructor, it is actually B's version of doSomething() that is being invoked. But since B's instance initializers have not yet executed the variable Bvar still has its default value of zero (which accounts for the Bvar=0 output).
It is only after control returns from A's constructor that B's instance initializers are allowed to execute, thereby initializeing Bvar to 2222. By the time the B() constructor calls doSomething() the instance initializer has already initialized Bvar to 2222 (which accounts for the Bvar=2222 output).

Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
Originally posted by ryan burgdorfer:
This seems to be a contradiction...
In the last red part, did you mean to say that when you initialize the der its variables are created on the stack?

Thank you ryan, I should have said:
When you initialize the der, the class variables for a der are created on the stack.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Initialization