I am making some revisions from the lecture slides and it says a constructor is executed in the following way:
If the constructor starts with this, recursively execute the indicated constructor, then go to step 4.
Invoke the explicitly or implicitly indicated superclass constructor (unless this class is java.lang.Object).
Initialise the fields of the object in the order in which they were declared in this class.
Execute the rest of the body of this constructor.
What I don't understand is that a constructor can never "start" with this, because even if it forms no class hierarchy/relationship then super() is inserted by default.
How would this fit in with the description above?
A constructor (for every class except java.lang.Object) has to start with either "super()", to call its superclass' constructor, or "this()", to call another constructor of the same class. If you don't include either of those in your constructor the compiler will insert a call to super(). It's fine for a constructor to start with a call to another constructor in the same class, as long as eventually a constructor in the class gets called that calls a superclass constructor.
I don't think you're right, or I don't understand the problem. From the Java Language Spec:
If a constructor body does not begin with an explicit constructor
invocation and the constructor being
declared is not part of the primordial
class Object, then the constructor
body is implicitly assumed by the
compiler to begin with a superclass
constructor invocation "super();", an
invocation of the constructor of its
direct superclass that takes no
arguments.
As such a constructor can start with this(...) which calls another constructor of the same class. Only when a constructor is called which does not start with either this(...) or super(...), super() is called automatically.
What I would say is that after an object is constructed super(...) has been called (if the class is not java.lang.Object).
here a more or less practical example for using this(...)
public class Car {
private final int numberOfDoors;
public Car(int doors) {
numberOfDoors = doors;
}
public Car() {
this(4); // default is 4 doors, calls the constructor above
}
}
the first statement in constructor body should be this or super , if nothing is there compiler by defalt keeps a super() keyword (with no argument).
so the Constructor body executes in this way:
Execution will happen on the basis of this or super keyword, then
it will execute all IIB's (as top down approach), then
it will execute all the statments kept by the programmer (like sop, initilization)
Class A{
A() {
this(10); //or super,....... execution statement 1
// executing IIB's, execution statement 2
System.out.println("from A()"); // execution statement 3
}
A(int i) {
System.out.println("from A(int)");
}
{
System.out.println("from IIB-1");
}
public static void main(String[] args){
A a = new A(); //calling constructor A()
System.out.println("from main");
}
{
System.out.println("from IIB-2");
}
}
Output:
from IIB-1
from IIB-2
from A(int)
from A()
from main
In Java, when you instantiate any object with new like C c = new C(); it delegate its super class constructor to create it first.
So in your case new C() --> Delegates to --> B() --> Delegates to A()
So execution flow is as below:
1) A() will Prints : 2
2) B() will calls B(1 ) prints 3 and control return to B() constructor
3) B() will prints : 4
4) C() will prints : 6
I hope it is now clear
Related
This question already has answers here:
Java order of Initialization and Instantiation
(2 answers)
Closed 1 year ago.
I am studying multilevel inheritance in java and stuck at this concept : that in a class hierarchy , constructors are called in order of derivation, from superclass to subclass.
I tried looking for the proper explanation on google but nothing satisfactory.
Please explain with example, it would really be helpful
I guess it's pretty obvious when you make it explicit:
class A {
A() {
System.out.println("3");
}
}
class B extends A {
B(String foo) {
super();
System.out.println("2" + foo);
}
}
class C extends B {
C(String foo) {
super(foo);
System.out.println("1");
}
}
When using these explicit constructor calls, you can see that super(...) is always the first instruction. Though this is what happens:
new C("foo"); will call the C constructor
first line in C constructor will call super constructor (B)
B constructor is called
first line in B constructor will call super constructor (A)
A constructor is called (prints 3)
when all lines of A constructor are done, it will return control to B constructor
B constructor will execute all lines after the super call (prints 2 + foo)
then it will return control to C constructor
C constructor will execute all lines after the super call (prints 1)
When you don't create an explicit constructor this code will still be run in exactly the same order.
It's basically the same as calling methods from within methods, or calling super methods. The only difference is, that you must call the super constructor before you execute any other code.
In the code that I have provided the overloaded constructor with argument which makes a call to the no-args constructor, which inturn should call the constructor of the object class in this case. So how does using the this() keyword execute the program correctly but not a direct call to the constructor.
public class S {
S() {
System.out.println("S()");
}
S(int i) {
this();
S();// The method S is undefined for type S
System.out.println("S(int i)");
}
public static void main(String[] args) {
S obj1 = new S();
System.out.println("----------");
S obj2 = new S(10);
System.out.println("----------");
}
}
Syntactically, S() is a method invocation, but you do not have a method called S.
this(); is special syntax for using another constructor in the same class.
To illustrate this point, I added:
void S() {
System.out.println("Method S()");
}
It now compiles, and the output is:
S()
----------
S()
Method S()
S(int i)
----------
A constructor is defined to initialize (construct) objects, therefore you can't call it.
S s = new S();//Correct
S(); //Incorrect, you are calling a method not a constructor.
new S();//Correct
this() is used to to pass arguments to constructor of the same class.
super() is used to pass arguments to parent constructor.
This is called explicit constructor invocation.
Note that when invoking a constructor from another constructor, it must be the first statement of the constructor else it won't compile.
How to invoke other constructors of the same class is defined by The Java Language Specification, section 8.8.7.1 Explicit Constructor Invocations:
• Alternate constructor invocations begin with the keyword this
(possibly prefaced with explicit type arguments). They are used to
invoke an alternate constructor of the same class.
• Superclass constructor invocations begin with either the keyword
super (possibly prefaced with explicit type arguments) or a Primary
expression. They are used to invoke a constructor of the direct
superclass.
I have the following code but I don't get why when I run this it prints "b" before printing "h hn x". Why does "b" get printed at all since I am not calling the superclass Building at all when I execute House().
class Building {
Building() {
System.out.print("b ");
}
Building(String name) {
this();
System.out.println("bn " + name);
}
}
public class House extends Building {
House() {
System.out.println("h ");
}
House(String name) {
this();
System.out.println("hn " + name);
}
public static void main(String[] args) {
new House("x ");
}
}
The zero-arg constructor of a superclass is implicitly called by the constructor of its subclass, automatically.
More generally, for
class B extends A
The constructor
public B()
{
//Your code
}
Actually looks like
public B()
{
super(); //Call the superclass constructor
//Your code
}
You can override this behavior by making an explicit call to some other superclass constructor. Note that if the implicit call to the constructor cannot be made (like if your no-arg constructor doesn't exist), then you will see an error.
The superclass constructor is always called whenever a subclass is being constructed. If the superclass constructor does not require any arguments, as is the case here, this call can be made implicitly.
If you were to introduce an argument in the constructor for Building, you'd get an error in House as it will require you to explicitly call the new superclass constructor.
Official resource:
From the Oracle javase tutoriel:
With super(), the superclass no-argument constructor is called. With
super(parameter list), the superclass constructor with a matching
parameter list is called. Note: If a constructor does not explicitly
invoke a superclass constructor, the Java compiler automatically
inserts a call to the no-argument constructor of the superclass. If
the super class does not have a no-argument constructor, you will get
a compile-time error. Object does have such a constructor, so if
Object is the only superclass, there is no problem.
If a subclass constructor invokes a constructor of its superclass,
either explicitly or implicitly, you might think that there will be a
whole chain of constructors called, all the way back to the
constructor of Object. In fact, this is the case. It is called
constructor chaining, and you need to be aware of it when there is a
long line of class descent.
Additional resource:
The section Constructor Chaining From the SCJP 6 book explains clearly what you are looking for with in a simple manner, it provides also a little more informations about this process:
We know that constructors are invoked at runtime when you say new on
some class type as follows: Horse h = new Horse(); But what really
happens when you say new Horse() ? (Assume Horse extends Animal and
Animal extends Object.)
Horse constructor is invoked. Every constructor invokes the constructor of its superclass with an (implicit) call to super(),
unless the constructor invokes an overloaded constructor of the same
class (more on that in a minute).
Animal constructor is invoked (Animal is the superclass of Horse).
Object constructor is invoked (Object is the ultimate superclass of all classes, so class Animal extends Object even though you don't
actually type "extends Object" into the Animal class declaration. It's
implicit.) At this point we're on the top of the stack.
Object instance variables are given their explicit values. By explicit values, we mean values that are assigned at the time the
variables are declared, like "int x = 27", where "27" is the explicit
value (as opposed to the default value) of the instance variable.
Object constructor completes.
Animal instance variables are given their explicit values (if any).
Animal constructor completes.
Horse instance variables are given their explicit values (if any).
Horse constructor completes.
Analogy with your example:
So when you said new House("x "), here is what happens:
The House(String name) invokes House() as specified by the keyword this().
The House() constructor implicitly calls super() which invoks the construcotr Building().
The Building() constructor implicitly calls super() which is the Object constructor.
The Object constructor completes
The Building() constructor will complete and print "b "
The House() constructor will complete and print "h"
The House(String name) constructor will complete and print "hn x ".
The result is "b h hn x "
NB: Building(String name) would be invoked if you added an explicit call from House() to super("someString"), in that case the result will be: "b bn someString h hn x "
In inheritance it is necessary to initialize all the fields present in super-class first, because those fields are get used in subclasses, for this before construction of your subclass super class constructor get called to initialize all the field present in your super class.
Super class constructor called when you construct subclass instance. In your code you are creating new House("x "); Instance of House.
It calls House parametrized constructor House(String name) at this time your super class implicit constructor get called.
If you step through program the call stack shows what's happing:
(you need to follow the call stack from bottom to top):
House(Building).<init>() line: 3
House.<init>() line: 2
House.<init>(String) line: 7
House.main(String[]) line: 12
First Main is called
Then in the House(name) constructor this() is called
This calls the House() constructor (because no argument is provided)
Now comes the interesting part: because the Default constructor is called and House is derived from Building, it is required to construct the Building first which by specification is the default constructor of the parent class Building.
I have some java Code:
class Protected{
int n = 1;
public Protected(){
System.out.println("Constructor of protected");
System.out.println("========================");
System.out.println("n = "+n);
System.out.println();
}
}
class Derived extends Protected{
Derived(){
System.out.println("Constructor of derived");
System.out.println("======================");
System.out.println("n = "+(n+1));
}
}
public class Demo{
public static void main(String args[]){
Derived ob2 = new Derived();
}
}
I got the output as:
constructor of protected
========================
n=1
constructor of Derived
========================
n=2
This is what I want:
constructor of Derived
========================
n=2
A superclass constructor must be called for every new instance of a subclass. If you don't supply an explicit call to a superclass constructor in your subclass constructor, then Java will insert an implicit call to the no-argument superclass constructor. This explains why you see the output of your superclass constructor.
To remove that output, you can do one of the following:
1) Remove the output statements from the superclass constructor.
2) Create another constructor in the superclass that doesn't output anything, and explicitly call it in the subclass constructor.
Section 8.8.7 of the JLS states:
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
This is what is happening implicitly:
class Derived extends Protected{
Derived(){
super(); // <--- This is called whether you want to or not
System.out.println("Constructor of derived");
System.out.println("======================");
System.out.println("n = "+(n+1));
}
There is absolutely no way to do this in Java; it would break the language specification. Don't put a print statement in the base class if the printing is not desired.
JLS 12 Execution / 12.5 Creation of New Class Instances
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor [...]
If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then [...]
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).
Execute the instance initializers and instance variable initializers for this class [...]
Execute the rest of the body of this constructor [...]
You should not extend the super class to get the desired output. Or You can define another overloaded Constructor in Super class and, you need to call it explicitly in sub class Constructor.
When a sub class Constructor invoked, before the constructor's body get executed, Super class Constructor will be called, Hence the output of you program.
I'm a beginner and currently reading inheritance and polymorphism. I'm having some confusion in terms of the keyword "extend" and how constructors are called. Here's the code:
public class Test {
public static void main(String[] args) {
new B();
}
}
class A {
int i = 7;
public A() {
System.out.println("i from A is " + i);
}
public void setI(int i) {
this.i = 2 * i;
}
}
class B extends A {
public B() {
setI(20);
System.out.println("i from B is " + i);
}
public void setI(int i) {
this.i = 3 * i;
}
}
I know that by calling B() in line 3, class A's constructor is invoked, and then B's is invoked (is that right?) and thus it displays "i from A is 7" and then "i from B is 60". But can someone explain the importance of this? Why is int i in B completely different from in i in A? Again, I'm having trouble following the "path" of the code after the line new B(). If someone could explain each step after B() is invoked, that would be much appreciated.
I'm having trouble following the "path" of the code after the line new
B(). If someone could explain each step after B() is invoked, that
would be much appreciated.
When calling new B(), the flow technically enters the constructor B() first. Constructors in Java always need to (eventually) chain to a higher constructor (recursively until the highest class, Object, is reached). Chaining is denoted by a super(...) or this(...) statement as the first statement of the constructor. If none is explicitly written, the parameterless super() is assumed. So, B() actually compiles as if it were written like this:
public B() {
super();
setI(20);
System.out.println("i from B is " + i);
}
Now you can clearly see that new B() calls B() which calls A() (which calls println and exits), then setI and finally println.
Why is int i in B completely different from in i in A?
The i is exactly the same field. The difference comes from the fact that you've invoked setI(20) between the two printouts, thus changing the value of i. If you remove the call to setI, you'll see that the value remains 7.
When you are creating your instance of B and you call the constructor B(), it will first call super(), which in your case will call A().
This prints i from A is 7, because 7 is your default that you are setting i to.
After super is called, it moves on to the next line, which is setI(20). This line sets the i in B to 60 because your setI(int i) method multiplies the parameter (20) by 3, then sets i to that value.
Then, you are printing i from B is 60 because i is now 60.
The Java language spec says
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
This means that when you write new B(), the first thing that the constructor for B does is to call the constructor for A. After the constructor for A has set i to 7, the constructor for B invokes setI(20), which changes the value of i to 60. There's only one i - it's not different in A and in B. It has simply changed value between one println and the next.
A subclass must always call the constructor of its superclass via super() or by invoking another constructor using super and the arguments of that constructor.
If you don't add super() explicitly, Java will do it for you behind the scenes.
class B extends A {
}
Is the same as calling:
class B extends A {
public B() {
super();
}
}
Knowing that, it should be apparent that calling new B(); will call the B constructor, which then calls the A constructor before finishing.
When you call to new B(), VM calls implicity super(), then a new A() is writing 7, but in your setI you are overwriting the method, it is because you see 60.
Use anotation #Override is allways a good idea.
BR