As far as I know init block is a block that is executed before any constructor whenever that constructor is used for creating object.But why is the rule contradicts here...
class SuperClass
{
SuperClass()
{
System.out.println("Super Class constructor");
}
{
System.out.println("Init block of super class");
}
}
class Child extends SuperClass
{
Child()
{
super();
System.out.println("Child Class constructor");
}
public static void main(String s[])
{
Child c1=new Child();
}
}
Here, as only child class object is formed, why is the init block of parent class called then?
Child is dependant on the parent class SuperClass. It gets / inherits properties from the parent. So, to construct the child, the parent has to be constructed first. That is why SuperClass's init blocks and constructors are called.
You can read through the JLS 12.5 for this topic. Check step 3 and 4 of the initialization order
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.
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.
Generally follow this rule,
class A{}
class B extends A{}
in this case,
while B-object instantiate, the sequence of calling is likewise,
B-Constructor -> A's Constructor -> before A's Constructor call A's All-Initialization block execute then A's Constructor then back to B's constructor like wise it works.
So, in your case,
Child object call to Child-constructor first,
but before go to it, it went to SuperClass-constructor, before proceed is first if any initialization block is there then it complete-here it's.
so SuperClass initialization block first execute then SuperClass's constructor and finally Child Constructor.
Related
As per constructor chaining base constructor should be called when a derived class object is created and assigned to base class reference.
And there is no default constructor in base class but then there is an explicit parameterized constructor, so java compiler does not provide default constroctor.
Without the statement "this(10);" compiler complains but then as soon as its added, compiler is fine with it. WHY??
I mean why does it not try to call the base class default constructor after adding "this(10);". It should have done a super call and then executed the added statement.
class Parent{
public Parent(int a) {
System.out.println(a);
}
}
class Child extends Parent{
public Child(){
this(10);//default value
}
public Child(int a) {
super(a);
System.out.println(a);
}
}
The Java Language Specification (§12.5) defines what happens when you create a new instance; I highlighted the most important parts for your question.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) 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.
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.
So, the key points are:
Your first constructor explicitly invokes the second constructor, so step 2 above applies; the second constructor is executed, and then step 3 is skipped.
Step 3 is where the superclass constructor gets called, so that means when a constructor invokes another constructor from the same class, then it does not directly invoke a superclass constructor.
However, if you delete this(10); from the first constructor, then the first constructor does not invoke another constructor of the same class, so step 3 applies, and a superclass constructor is implicitly invoked. This causes an error because there is no superclass constructor that can be implicitly invoked (with no arguments).
The default/implicit constructor is there only if there is no other constructor.
By adding
public Parent(int a) {
System.out.println(a);
}
you remove the default constructor of Parent.
If you want to keep the default constructor, you can write it yourself like this:
public Parent(){
}
The following constructor
public Child(){
}
will be automatically replaced to
public Child(){
super();
}
This replacement will happen if there is no constructor call(this() or super()) in the first line.
This secures that a super constructor is called in any case.
The replacement will fail if there is no constructor without arguments in the super-class (if you have replaced the default constructor with a parameterized constructor).
Because if you don't add this() to Child() constructor - compiler will insert super() statement and thus expect no-arg constructor in Parent class.
class Parent{
public Parent(int a) {
System.out.println(a);
}
}
class Child extends Parent{
public Child(){
// this(10);// Commenting this(10) as if it did not exist.
super() // inserted by compiler unless you put this() or super() yourself
}
public Child(int a) {
super(a);
System.out.println(a);
}
}
I've put this code in the compiler
package com.employer.constractor;
public class ConstractorDemo extends A{
public ConstractorDemo(){
System.out.print("Demo");
}
public static void main(String[] args){
new ConstractorDemo();
}
}
class A {
A(){
System.out.print("A");
}
}
And it gave "ADemo"
why?
I'll appreciate any detailed answer for this case
and mention how compiler will deal exactly with that
The constructor of a base class (class A in your case) is always executed before the constructor of the class you are instantiating (class ConstractorDemo in your case). That's why A is printed before Demo.
This constructor :
public ConstractorDemo(){
System.out.print("Demo");
}
is equivalent to :
public ConstractorDemo(){
super (); // prints A
System.out.print("Demo"); // prints Demo
}
The child constructor is invoked first. The first line in the child constructor will be a call to super. WHich gives you the illusion that the parent will be invoked first. But in reality the child class's constructor calls the parent class's constructor
When you invoke a child constructor, it automatically chain the calls to it's all super classes until the chain reaches to Object class.
Though you are not invoking Invoking a super class constructor doesn't mean that you are executing only Child class constructor alone. There is a interesting fact that your super class constructors(till n'th super class, which is Object class constructor) also calls in that process(shown in your code). you can observe when you invoke any Child constructor. There is a chain call to the immediate parent class constructor from the current class. And the call continues until the Object class constructor invokes since that the possible most Parent classes super class is.
Thumb rules
If you call any specific super constructor (super or super(args)),
then that specific super constructor invokes.
If you are not calling any specific constructor, then default super
constructor(super()) invokes.
base class constructor is always executed before the class Level Constructor . it automatic call super class . So First Awill print then after that Demo as per Your example. Thanks
Whenever a subclass's constructor is called , the first default statement in it is super(); which is automatically added by the compiler,
The super(); will invoke the constructor of superclass and so, first it will execute A() and then ConstractorDemo()
Refer to this : https://www.javatpoint.com/super-keyword
Even if you want to specify super(); it needs to be the first statement of your constructor else it will give you compile time error!
Your Constructor is like this :
public ConstractorDemo()
{
super(); // u didn't specified this but compiler will automatically add it
System.out.print("Demo");
}
Given Main.java:
public class Main{
public static void main(String[]args){
A a = new B();
a.print();
}
}
class A{
A() {print();}
void print() { System.out.println("A"); }
}
class B extends A{
int i = 4;
void print() { System.out.println(i); }
}
Results in:
0
4. But why doesn't a.print output "A" if it is referencing Class A? How do I know when one method will called be over another in cases like this? Why is A's constructor being called and still using B's method?
Calling a.print() prints 4 because of polymorphism. The method called depends on the runtime type of a, which is B. It doesn't matter when it's called; polymorphism applies always.
Both times, B's print method is called. Once is from A's constructor, which is called by the default constructor in B. The other time is your explicit call in main.
The reason that the first printing yields 0 and not 4 is because at the time that print is called, A is still being constructed. That is, the A constructor is still being executed. Before a superclass constructor returns, nothing is initialized in the subclass yet, not even variable initializers. The value 4 is assigned after the superclass constructor completes, but before the rest of the subclass constructor completes. Because the variable initializers haven't run yet, the default value of 0 (it would be false for booleans and null for objects) is the value of i in the first printing.
This order is listed by the JLS, Section 12.5:
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 to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) 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.
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.
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.
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.
(bold emphasis mine)
This is an example of why it's a bad idea to call a method that can be overridden from a constructor. The subclass state isn't initialized yet.
In case of Overridden methods (like print() in your example), object type decides which method to be invoked, not the reference type.
B doesn't have any constructor, so its default constructor won't do anything except calling A's constructor.
Now when B's default constructor is called, it calls A's constructor (keep in mind i is still not set, so default value 0). A's constructor calls print(), now as object is of actually B it calls B's print() and it prints 0 (remember i was not set).
Now once these constructor calls completes B's code gets executes which sets i to 0. Now calling print() will again get you to B's print() (as object is of B only) which will print 4.
"DEBUGGING IS THE KEY"
Given Main.java:
public class Main{
public static void main(String[]args){
A a = new B();
a.print();
}
}
class A{
A() {print();}
void print() { System.out.println("A"); }
}
class B extends A{
int i = 4;
void print() { System.out.println(i); }
}
Results in:
0
4. But why doesn't a.print output "A" if it is referencing Class A? How do I know when one method will called be over another in cases like this? Why is A's constructor being called and still using B's method?
Calling a.print() prints 4 because of polymorphism. The method called depends on the runtime type of a, which is B. It doesn't matter when it's called; polymorphism applies always.
Both times, B's print method is called. Once is from A's constructor, which is called by the default constructor in B. The other time is your explicit call in main.
The reason that the first printing yields 0 and not 4 is because at the time that print is called, A is still being constructed. That is, the A constructor is still being executed. Before a superclass constructor returns, nothing is initialized in the subclass yet, not even variable initializers. The value 4 is assigned after the superclass constructor completes, but before the rest of the subclass constructor completes. Because the variable initializers haven't run yet, the default value of 0 (it would be false for booleans and null for objects) is the value of i in the first printing.
This order is listed by the JLS, Section 12.5:
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 to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) 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.
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.
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.
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.
(bold emphasis mine)
This is an example of why it's a bad idea to call a method that can be overridden from a constructor. The subclass state isn't initialized yet.
In case of Overridden methods (like print() in your example), object type decides which method to be invoked, not the reference type.
B doesn't have any constructor, so its default constructor won't do anything except calling A's constructor.
Now when B's default constructor is called, it calls A's constructor (keep in mind i is still not set, so default value 0). A's constructor calls print(), now as object is of actually B it calls B's print() and it prints 0 (remember i was not set).
Now once these constructor calls completes B's code gets executes which sets i to 0. Now calling print() will again get you to B's print() (as object is of B only) which will print 4.
"DEBUGGING IS THE KEY"
I dont know whether this question has been asked before or not .I searched but couldn't find any duplicate question. If you find any related question please mention the link.
public class Exp
{
Exp()
{
System.out.println("Hello"); //3
}
{ System.out.println("Hello")}; //1
{ static{System.out.print("x");} //2
}
The order of printing of messages is 2,1,3.
What are the significance of these lines 1 & 2 and why that exec order
Line "1" is an instance initializer, which runs when an object is first created, before any constructors are called.
Line "2" is a static initializer, which runs when a class is first loaded, before any objects are created.
Section 12.5 of the JLS specifies when instance initializers are run:
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 to newly created parameter
variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation
(§8.8.7.1) 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.
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.
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.
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.
(emphasis mine)
The rest of the body of the constructor is executed after the instance initializer.
static blocks of a class are executed during class loading along with constants (static final members). 3 is invoked when the object is instantiated.
For you to understand better debug the code through your IDE to understand the sequence of execution.
See http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {
// whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
The reason for the execution order is, in non-static block you might want to use static members, but in static block you cannot use non-static members. So it makes sense to execute static block first.
non-static block allows you to abstract the code that every constructor needs to execute, therefore it gets executed before constructor.
More detailed order of execution:
1.static block of superclass
2.static block of this class
3.non-static block of superclass
4.constructor of superclass
5.non-static block of this class
6.constructor of this class