I thought that super(); means almost the same as we call the superclass constructor, but it doesnt.
class A {
A() {
foo();
}
void foo() {
System.out.print("A");
}
}
class B extends A {
void foo() {
System.out.print("B");
}
B() {
super();
super.foo();
}
}
When I call new B(); it prints BA why? I was debuging it and super() call constructor of A but it prints B(this is what Im not understanding), and why after this super.foo() prints A as it should. Can someone explain how does it works?
The reason it prints BA:
you call new B();
B constructor calls A constructor (your super() call)
A constructor calls foo
foo() is overridden in B, so it resolves to B.foo()
B.foo() prings "B"
B.foo() returns, and A constructor returns
B constructor moves to next call, which is to super.foo()
Because of the "super" qualification, this resovles to A.foo()
A.foo() prints "A"
The end
Why does it print "B" from A's call to foo()? Because foo() is an instance method, "this" is an instance of B, and B has a method with the same signature as A.foo, so this resolves to the subclass method B.foo. This is called virtual method resolution and is a fundamental concept of object-oriented programming. The terminology is that B.foo overrides A.foo.
Your program flow is as follows:
The constructor of B is called.
It calls the constructor of A with the super();. As an aside, that line is unnecessary and would be done automatically if left out.
The constructor of A calls foo() of B. The call foo(); is to the B version of foo() because the object is an instance of B, and the B version of foo() overrode the A version of foo(). So you get a 'B' printed.
The constructor of A returns to the constructor of B, which calls super.foo();. This calls the A version of foo() because you specifically told it to do so with the "super" prefix. So it prints an 'A'. (Note that this is not a call to a constructor, in case you were confused about that.)
The reference in one of the comments (What is virtual method calling in java?) explains more about this.
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.
Hello everyone,
I am very surprise to see the following program's output:
class A{
int f() {return 0;}
int g() {return 3;}
}
class B extends A{
int f() {return 1;}
int g() {return f();}
}
class C extends B {
int f() {return 2;}
}
public class Test {
public static void main(String args[]){
A ref1 = new C();
B ref2 = (B)ref1;
System.out.println(ref2.g());
}
}
Please help me to explain the code.
You are creating an instance of C and assigning it to the ref1 with type A. Further you are declaring a variable ref2 of type B which get assigned the value of ref1. The value of ref1 is still an instance of C even if you are viewing it by the type of class A.
Calling ref2.g() executes the method g() on the instance of the variable ref2. This is still the one and only created instance of C. Looking on it by the type of class B doesn't change the implementation of the instance the variable ref2 is referring to.
Let us extend class C by a method int h() { return 5; }. Using ref2 you cannot call method h() because the type of the variable is B. But h() is still present on the instance ref2 is referring to. If you extend the main method by
C ref3 = (C) ref2;
System.out.println(ref3.h());
this will output 5. But assigning the value of ref2 to ref3 and calling on it h() implies that the value of ref2 and ref3 (and ref1) is the same.
System.out.println(ref2 == ref3);
This outputs true. So both variables refer to the same object, the instance of C.
I will try to explain by steps:
Reference ref1 points to the instance of the class C.
Reference ref2 points to the same instance of the class C. No matter that it was done with explicit typecast, the instance in the heap still has the type C. Again:
ref2 has the type B;
object instance that ref2 is pointed to has the type C.
When we call to ref2.g(), JVM actually try to find method g() in class C (because object instance in heap has the type C, as was stated above). Because there is no method g() in class C, JVM moves to the parent class B, finds method g() in it, and calls it.
Call to method g() in class B leads to method f(). JVM again try to find that method initially in class C, finds it and return value 2.
This code represents overriding. And in overriding at runtime the jvm decides that which method to call (also called late binding).
Now come to code, the class C has the overridden method f() and in the code you have type-casted the reference of class A (ref1) to class B and called to g() method, so at runtime the jvm will call g() method of class B and ref2 is a reference of class B, which is pointing to class C object, so at runtime the f() method of class C has binded and it will call f() method of class C.
It's actually part of one interview question I got confused.
class A
{
public A()
{
System.out.println("A") ;
}
}
class B extends A
{
public B()
{
System.out.println("B") ;
}
}
A a1 = new B();
System.out.println() ;
A a2 = (A) new B() ;
So the question is what is the print out?
At first I thought it should print out like
B
A
B
A
But after I run at home, it gives
A
B
A
B
I understand it's inheritance and then upcasting B to A, and it's legal syntax as well, but why is A print before B?
why is A print before B?
Because the body of the superclass constructor is executed before the body of the subclass constructor, basically.
Think of your B() constructor as implicitly:
public B()
{
super(); // This invokes A's constructor
System.out.println("B") ;
}
The full details are in JLS 12.5. In particular:
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.
The constructor of the parent class A is called before that of the subclass B. In other words, it is equivalent to:
public B() {
super();
System.out.println("B");
}
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
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