As i knew, constructors,Instance Initialization block are NOT inherited to the subclass, but below code inherits the super-class constructor, why it is calling?
Expected output is :
from cons 2
but its showing output like:
--IIB--
from cons 1
from cons 2
WHY? this output , *As i know "sub class should not inherit Constructor & IIB block"*
Please help me to make clear this concept.
public class X
{
{
System.out.println("--IIB--");
}
X()
{
System.out.println("from cons 1");
}
}
class Y extends X
{
Y()
{
System.out.print("from cons 2");
}
}
class Z
{
public static void main(String args[])
{
Y ob=new Y();
}
}
This is happening because this:
Y()
{
System.out.print("from cons 2");
}
actually becomes
Y()
{
super(); //Call to X's constructor made here even if you don't call it
System.out.print("from cons 2");
}
The reason for this is that every Y is also an instance of X. It's necessary to call that parent constructor first, before any of the child constructor executes, to guaranteee that the parent attributes are ready to go.
Edit: here's the example to show that "super class constructors are not inheriated by the subclass":
class A {
A(int intForA) {
//Do stuff...
}
}
class B extends A {
B() {
this(3); //Won't compile! A's constructor isn't inherited by B
}
}
Instead, we do this:
class B extends A {
B() {
super(3); //This compiles; we're calling A's constructor from B
}
}
"The Java compiler copies initializer blocks into every constructor."
- http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
"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."
- http://docs.oracle.com/javase/tutorial/java/IandI/super.html
When you call the sub class constructor, it internally calls the super class constructor using the super()(Note section in the linked page at the last) and in your case, the super class for Y is X. Also, the instance blocks are copied in the constructor and thus are executed when any of the constructors of that class are called.
From the init block docs
Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor.
Thus the output in the below order.
--IIB-- - From the instance block which gets placed inside the constructor of X.
from cons 1 - when super() is called inside Y()
from cons 2 - the SOP in Y()
in you code Y extends X so ideally when you create Y class object it also create X class object. So its block gets execute first then constructor of X and then constructor of Y .
Hence you are getting output like that.
Related
There is two classes Super1 and Sub1
Super1.class
public class Super1 {
Super1 (){
this.printThree();
}
public void printThree(){
System.out.println("Print Three");
}
}
Sub1.class
public class Sub1 extends Super1 {
Sub1 (){
super.printThree();
}
int three=(int) Math.PI;
public void printThree(){
System.out.println(three);
}
public static void main(String ...a){
new Sub1().printThree();
}
}
When I invoke the method printThree of class Sub1 I expected the output to be:
Print Three
3
Because Sub1 constructor calling the super.printThree();.
But I actually get
0
Print Three
3
I know 0 is default value of int but how it is happening ?
You're seeing the effects of three things:
Default super-constructor calls, and
Instance initializers relative to super calls, and
How overridden methods work
Your Sub1 constructor is really this:
Sub1(){
super(); // <== Default super() call, inserted by the compiler
three=(int) Math.PI; // <== Instance initializers are really inserted
// into constructors by the compiler
super.printThree();
}
(Surprising, I know, but it's true. Use javap -c YourClass to look. :-) )
The reason it looks like that is that the superclass must have a chance to initialize its part of the object before the subclass can initialize its part of the object. So you get this kind of interwoven effect.
And given that that's what Sub1 really looks like, let's walk through it:
The JVM creates the instance and sets all instance fields to their defaults (all bits off). So at this point, the three field exists, and has the value 0.
The JVM calls Sub1.
Sub1 immediately calls super() (Super1), which...
...calls printThree. Since printThree is overridden, even though the call to it is in the code for Super1, it's the overridden method (the one in Sub1) that gets called. This is part of how Java implements polymorphism. Since three's instance initializer hasn't been run yet, three contains 0, and that's what gets output.
Super1 returns.
Back in Sub1, the instance initializer code for three that the compiler inserted (relocated, really) runs and gives three a new value.
Sub1 calls printThree. Since three's instance initializer code has now run, printThree prints 3.
With regard to this instance initializer code getting moved into the constructor, you might be wondering: What if I have more than one constructor? Which one does the code get moved into? The answer is that the compiler duplicates the code into each constructor. (You can see that in javap -c, too.) (If you have a really complicated instance initializer, I wouldn't be surprised if the compiler effectively turned it into a method, but I haven't looked.)
It's a bit clearer if you do something really naughty and call a method during your instance init: (live copy)
class Super
{
public static void main (String[] args) {
new Sub();
}
Super() {
System.out.println("Super constructor");
this.printThree();
}
protected void printThree() {
System.out.println("Super's printThree");
}
}
class Sub extends Super
{
int three = this.initThree();
Sub() {
this.printThree();
}
private int initThree() {
System.out.println("Sub's initThree");
return 3;
}
protected void printThree() {
System.out.println("Sub's printThree: " + this.three);
}
}
Output:
Super constructor
Sub's printThree: 0
Sub's initThree
Sub's printThree: 3
Note where "Sub's initThree" came in that sequence.
When the instance is created, the Sub1 constructor is called.
The first instruction in any constructor is a call to the superclass constructor. If you don't have an explicit call, there will be an implicit call to the no-args constructor of Super1.
The no-args constructor is calling this.printThree(). This method is overridden in Sub1. Now, this part may be confusing, but even if the code is in the superclass, this.method() still refers to the overriding method.
So it's calling the printThree() in Sub1, which prints the uninitialized value of the variable three - 0.
Now that the superclass's constructor is done, it completes Sub1 constructor, which uses super.printThree(). Since it specifically says super, the method from Super1 is used rather than the overriding one. This prints the Print Three.
Now the Sub1 constructor is also done, and main calls the new instance's printThree(). Now three is already initialized, so you get the output 3.
While previous answers gave you clear answer to what is happening, they did not gave you any pointers on how to avoid your problems in the future, so I would also like to add my input on this.
If you are going to inherit, then you should make the super class constructor as "dumb" as possible. For example
public class Super{
private int a,b;
public Super(int a, int b) {
this.a = a;
this.b = b;
}
//all the methods operating on the data provided by constructor
}
and then having sub constructor like this
private int c,d;
public Sub(int a, int b) {
super(a,b);
c = a;
d = b;
}
Is perfectly fine and is going to give you minimal side-effects, while keeping the functionality of the parent class.
But having
public Super(){
method1();
method2();
}
and then having sub do this
public Sub(){
super.method1();
super.method2();
}
Is really asking for trouble and possible hard to track bugs. The less the object does during initialization, the better, because it gives the childs flexibility.
Managing inheritance is like being dumb manager vs clever manager. Dumb manager calls Tim and Tracy employee, because they are both employees, and their jobs as Accountant and HR manager are just tags. Clever manager knows Tim and Tracy are Accountant and Manager and does not care that much that they are basically just employees.
I have following classes:
public abstract class AClass {
public AClass() {
aMethod();
}
abstract protected void aMethod();
}
public class SubClass extends AClass {
private int x = 5;
private static final int y = 6;
#Override
protected void aMethod() {
System.out.println("x: " + x + " | y: " + y);
}
}
public class Main {
public static void main(String[] args) {
new SubClass();
}
}
Running Main prints the following: x: 0 | y: 6
Why does 0 get printed for x?
The reason of the misbehaviour is a wrong initialization sequence:
new SubClass() executes AClass constructor
AClass constructor calls aMethod()
aMethod() shows x (which is 0 so far) and y which is 6 because of being static)
SubClass initialize its non-static fields, so x becomes 5.
To avoid surprizes, never call virtual methods (esp. overriden) in constructors
The static field is initialized as soon as the class is initialized (after loading). Now when you call
new SubClass() the following things happen.
Constructor of SubClass is called as the first statement of SubClass (implicitly)
Constructor of SuperClass is called. --> you are checking value of x here
Once SuperClass constructor's execution completes, then instance level fields of SubClass are initialized. So x will be initialized here.
Initialization order. aMethod() is called before the line private int x = 5
Playing round with code examples like this is a great way to learn the order in which things are executed. Try adding a static and non-static initialization block too.
The result is because the super class constructor is called before the members are initialized.
In your case the following sequence is executed:
Call to constructor SubClass
immediate call to constructor AClass
call of method aMethod()
initializing of members of SubClass
This is also the reason why you should not call any overrideable methods from a constructor as the called method may access the state of an object that is not fully initialized.
private static final int y = 6;
Value of y is 6 when the constructor calls aMethod(), because it is static and is initialized while class loading.
private int x = 5;
While this initialization is appended at the end of your constructor body. It means while aMethod is being executed, the variable x has still default value i.e 0.
Default constructor of SubClass would look like
SubClass() {
super();
//All instance initialization are performed here.
}
Because when you created an instance of the Subclass it invokes the constructor of its super class AClass, and at this point, x was not yet set that's why it gets the default value of 0.
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
In an interview I was given the following code:
public abstract class Base {
public int x = 1;
public Base() {
foo();
}
public abstract void foo();
}
public class Derived extends Base {
int x = 2;
#Override
public void foo() {
System.out.println("Derived: "+x);
}
}
class Main {
public static void main(String... args) {
Base base = new Derived();
base.foo();
}
}
They asked:
What will be printed?
If we were using C++ I think the code should give a compilation error because when the Derived constructor is called first the constructor of the Base class is called. At this point the foo method doesn't exist.
In addition I know that first the inherited class constructor is called, before all the
variables is created.
However in Java we get:
Derived: 0
Derived: 2
Why?
I know that like in C++ Java inheritance is based always on virtual tables,
and the constructor of the Base class is called before the constructor of the Derived class.
This is the order in which the code is executed. More details follow.
main()
invokes Derived.<init>() (the implicit nullary constructor)
invokes Base.<init>()
sets Base.x to 1.
invokes Derived.foo()
prints Derived.x, which still has the default value of 0
sets Derived.x to 2.
invokes Derived.foo().
prints Derived.x, which is now 2.
To completely understand what is going on, there are several things you need to know.
Field Shadowing
Base's x and Derived's x are completely different fields which happen to have the same name. Derived.foo prints Derived.x, not Base.x, since the latter is "shadowed" by the former.
Implicit Constructors
Since Derived has no explicit constructor, the compiler generates an implicit zero-argument constructor. In Java, every constructor must call one superclass constructor (with the exception of Object, which has no superclass), which gives the superclass a chance to safely initialize its fields. A compiler-generated nullary constructor simply calls the nullary constructor of its superclass. (If the superclass has no nullary constructor, a compilation error is produced.)
So, Derived's implicit constructor looks like
public Derived() {
super();
}
Initializer Blocks and Field Definitions
Initializer blocks are combined in declaration order to form a big block of code which is inserted into all constructors. Specifically, it is inserted after the super() call but before the rest of the constructor. Initial value assignments in field definitions are treated just like initializer blocks.
So if we have
class Test {
{x=1;}
int x = 2;
{x=3;}
Test() {
x = 0;
}
}
This is equivalent to
class Test {
int x;
{
x = 1;
x = 2;
x = 3;
}
Test() {
x = 0;
}
}
And this is what the compiled constructor will actually look like:
Test() {
// implicit call to the superclass constructor, Object.<init>()
super();
// initializer blocks, in declaration order
x = 1
x = 2
x = 3
// the explicit constructor code
x = 0
}
Now let's return to Base and Derived. If we decompiled their constructors, we would see something like
public Base() {
super(); // Object.<init>()
x = 1; // assigns Base.x
foo();
}
public Derived() {
super(); // Base.<init>()
x = 2; // assigns Derived.x
}
Virtual Invocations
In Java, invocations of instance methods normally go through virtual method tables. (There are exceptions to this. Constructors, private methods, final methods, and methods of final classes cannot be overridden, so these methods can be invoked without going through a vtable. And super calls do not go through vtables, since they are inherently not polymorphic.)
Every object holds a pointer to a class handle, which contains a vtable. This pointer is set as soon as the object is allocated (with NEW) and before any constructors are called. So in Java, it is safe for constructors to make virtual method calls, and they will be properly directed to the target's implementation of the virtual method.
So when Base's constructor calls foo(), it invokes Derived.foo, which prints Derived.x. But Derived.x hasn't been assigned yet, so the default value of 0 is read and printed.
Obviously, only the derived class's foo() is called.
It prints 0 in the first time because it happens before assigning x = 2, which happens only in the constructor of Derived, after Base's initialization is complete. It prints 0 and not 1, because Derived.x is being accessed and not Base.x, and it was not initialized yet, and is still 0. The declaration of x in Derived hides the field in Base, so when Derived is printing x, it prints Derived.x.
EDIT: activation order when creating Derived(): [schematic]
1. create Base:
1.1. assign Base.x = 1
1.2. invoke foo()
1.2.1 print Derived: Derived.x //Derived.x was not initialized here yet!
2. assign Derived.x = 2
The second is trivial and expected [in my opinion at least].
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