*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes this(i) 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 "this(i)" Watch "this(i)" New topic
Author

this(i)

Mike Lin
Ranch Hand

Joined: Oct 29, 2002
Posts: 48
What's wrong? Why?
class This{
int i=0;
This(){
this(i);
}
This(int i){
}
}

cannot reference i before supertype constructor has been called
this(i);
^
1 error


SCJP1.4 <br />Best wishes!<br />中国人!
C. Nimo
Ranch Hand

Joined: Mar 23, 2004
Posts: 82
Hi.
You are trying to reference i from the constructor.
Try making i a static variable.
A constructor belongs in the class level, and i is an instance-level variable. By making i static, you move it to the class level, and there the constructor can use it.
Nimo.
Suresh Thota
Ranch Hand

Joined: Sep 24, 2003
Posts: 152
Hi Mike,
As you know the first statement in a constructor will always be the call to super constructor or to this. Unless this first line finishes execution you instance variables will not be initialized.
But static variables are initialized during class loading and they are available in your call this(i).
PS: I see kanji's in your signature. Are you from japan/china?
Cheers
-Suresh


SCJP 1.6
Mike Lin
Ranch Hand

Joined: Oct 29, 2002
Posts: 48
thanks .
I can understand both.
BUT, What I want to prove is that instance variables is initiated before CONSTRUCTOR is called.AS following:
class Init{
int i=prt("non-static");
static int prt(String a){
System.out.println(a);
return 6;
}
Init(){
System.out.println("Constructor");
}
public static void main(String a[]){
Init i=new Init();
}
}
Since instance variables is initiated before CONSTRUCTOR is called.WHY we CANNOT trying to reference i from the constructor???
hi,Suresh
PS: My singnature is not kanji's BUT Chinese characters ."中国人" means Chinese :-). AND. I am a Chinese!
[ April 05, 2004: Message edited by: Mike Lin ]
[ April 05, 2004: Message edited by: Mike Lin ]
Suresh Thota
Ranch Hand

Joined: Sep 24, 2003
Posts: 152
Mike,
Your asssumption is wrong. Instance variables are *NOT* initialized before super/this call is finished. I modified your code to prove my point.

O/P:
non-static
In this(x)
Constructor
Hope i'm clear.
Cheers
-Suresh
[ April 05, 2004: Message edited by: Suresh Thota ]
Mike Lin
Ranch Hand

Joined: Oct 29, 2002
Posts: 48
hi,
Your Example CANNOT prove that instance variables are *NOT* initialized before super/this call is finished.
Because "non-static" is the FIRST output line !!!That means non-static varialbes is initialized before constructor is called.
[ April 05, 2004: Message edited by: Mike Lin ]
Suresh Thota
Ranch Hand

Joined: Sep 24, 2003
Posts: 152
ok. My example is wrong. But I still stand on my word. Looking to frame an example to prove my point.
Cheers
-Suresh
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Although the example given by Suresh was incorrect, the idea is correct. From the JLS, §12.5 Creation of New Class Instances, this is the order of operations when we create a new instance:

1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
2. If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5. (In some early implementations, the compiler incorrectly omitted the code to initialize a field if the field initializer expression was a constant expression whose value was equal to the default initialization value for its type.)
5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally. In the example:

Notice that we first invoke the parent constructor or, if there is an explicit invocation of this, we move to that constructor. Once there, we, again, invoke the parent constructor and, once that is complete, we perform instance member initializers. Once the instance member initializers are executed, we go on to finish the rest of the constructor.
I hope that helps,
Corey


SCJP Tipline, etc.
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
In addition, here's a quick example that shows that a parent constructor is invoked prior to the instance member initializers of the child class:

Corey
sai kumar
Ranch Hand

Joined: Mar 31, 2004
Posts: 72
Hi Corey,
How is that we have 0 followed by 2 in the output. I was expecting 1 followed by 2, as when the constructor of the superclass is invoked implcitly,the first thing that happens is the superconstructor instance variable get initialized, i.e, i becomes 1 then the constructor execution continues and calls the getI() method which should have printed 1( :roll: how is that 0). After which the instance variables of the class Test are initialized (i.e, i becomes 2) and now the remaining part of the constructor prints 2.
Please clarify this.
thx.
bye
sk
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Originally posted by sai kumar:
How is that we have 0 followed by 2 in the output.

The reason for this is that the method getI() is overridden in the subclass, Test. Therefore, in the constructor of SuperTest, we invoke the method getI(). As this method is overridden and we're really dealing with an object of type Test, we invoke the getI() method that is part of Test, not the one that is part of SuperTest. Doing so results in the value of i contained in Test, not SuperTest, being returned. That variable hasn't yet been initialized so it contains the default value of 0.
I hope that helps,
Corey
sai kumar
Ranch Hand

Joined: Mar 31, 2004
Posts: 72
Thx Corey, that was an imp concept i missed.
bye
sk
Mcgill Smith
Ranch Hand

Joined: Nov 11, 2003
Posts: 178
quote Corey :
The reason for this is that the method getI() is overridden in the subclass, Test. Therefore, in the constructor of SuperTest, we invoke the method getI(). As this method is overridden and we're really dealing with an object of type Test, we invoke the getI() method that is part of Test, not the one that is part of SuperTest. Doing so results in the value of i contained in Test, not SuperTest, being returned. That variable hasn't yet been initialized so it contains the default value of 0.
=======================================================

quote Corey:
we invoke the getI() method that is part of Test, not the one that is part of SuperTest
-----------------------
why (A :1) if getI() method of Test is invoked and not the one that is part of SuperTest
static methods and variables are called on the reference Type's and
instance methods and instance variable are called on the object the reference is pointing too.
[ April 05, 2004: Message edited by: Mcgill smith ]

Regards
Mcgill
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
By making i static, you have modified the order in which things get initialized. Static members are initialized when a class is "loaded" rather than what it is instantiated. By the time you get to class instantiation, the classes are already loaded. Therefore, before you ever invoke the method getI(), both SuperTest.i and Test.i have been initialized.
If you take a look at the JLS, §12.4.1 When Initialization Occurs, you'd see these key statements:

Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class.
...
Before a class is initialized, its direct superclass must be initialized...
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
...
T is a class and a static method declared by T is invoked.

So, in this case, Test is initialized as soon as we invoke main - it is a static method. As a superclass must be initialized prior to a subclass, we also initialize SuperTest at this point. At that point, we go through the initializers for any static fields in Test and SuperTest. Therefore, both SuperTest.i and Test.i have been assigned their values (1 and, respectively) prior to Test.main being executed.
Keep in mind that, in this case, we're talking about initializaton of a class, not instantiation of an object. They're very different processes, but the terminology (such as initialization) is common between the two so it is imporant to keep in mind which case we're dealing with.
I hope that helps,
Corey
Jon Egan
Ranch Hand

Joined: Mar 24, 2004
Posts: 83
I wrote up this detailed expanation of the previous example befre I noticed the difference in your latest question... here's that, so I haven't wasted my time
The call stack of the original problem ( without the "static" ) :

note that we are in the println() call in the superclass constructor, which prints "A:", then calls getI(), and we get the subclass implementation of getI() but we are still inside the parent class constructor.
To continue:

</COMPLETELY_IRRELEVANT_DISCUSSION>
ok, now on to the actual latest question:
in this case, the polymorphism no longer applies (that is, we no longer get the subclass' implementation of getI() while in the superclass' constructor).
Static methods are called based on the reference upon which they are invoked, not the underlying object type. The distinction:
Polymorphism: Regular (non-static) methods are called based on the type of the object, regardless of the type of the reference.
Hiding: Static methods are exactly the opposite - you get the method based on the type of the reference, regardless of the type of the underlying object.
So even though the object being constructed is a Test, the implicit "this" reference in the superclass constructor call to getI() is of type SuperTest, and that is what determines which version of the method is called. So you get "A: " followed by the value of the SuperTest class variable i, which is 1.
-- Jon Egan
Mcgill Smith
Ranch Hand

Joined: Nov 11, 2003
Posts: 178
quote Mike:
What's wrong? Why?
class This{
int i=0;
This(){
this(i);
}
This(int i){
}
}

cannot reference i before supertype constructor has been called
this(i);
^
1 error
--------------------------------------------
note : Object is super class of every java class
so
class This extends Object.
An explicit constructor invocation statement(using this or super) in a constructor body may not refer to any instance variables or instance methods declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.

class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
}
class ColoredPoint extends Point {
static final int WHITE = 0, BLACK = 1;//------class variables
int color;//---------------------instance variable
ColoredPoint(int x, int y) {
this(x,y,color);//----------->wrong
//this(x, y, WHITE);--------ok

}
ColoredPoint(int x, int y, int color) {
super(x, y);
this.color = color;
}
}
A compile-time error would occur, because an instance variable cannot be used within a superclass constructor invocation.
[ April 05, 2004: Message edited by: Mcgill smith ]
Suresh Thota
Ranch Hand

Joined: Sep 24, 2003
Posts: 152
Corey,
Your example was brilliant. Yesterday I was thinking of framing this kind of example where superclass constructor calls the subclass method. ofcourse, I drew the idea from a famous mock question in javacertificate.com
Cheers
-Suresh
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: this(i)