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);
}
}
Related
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");
}
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.
This question already has answers here:
Why is constructor of super class invoked when we declare the object of sub class?
(18 answers)
Closed 9 years ago.
abstract class A {
abstract void method();
}
class B extends A {
B() {
}
void method() {
}
}
class C extends B {
C() {
}
}
When I instantiate class C in main, it automatically calls the constructor for B (parent class). Is that normal or am I doing something wrong?
There is nothing wrong, there is implicit call to super constructor.
You haven't written any constructor for class C so default constructor will be provided by compiler which will be.
C(){
super();
}
If default constructor is provided, then there is a call to super().
In your case, C extends B so constructor of B gets called.
If you do not a class with any other class, then also by default it extends Object class. So Object class constructor will get called.
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.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.7
When you instantiate a C there will be constructor calls for C, B, A, and Object. A C has to be able to behave as any direct or indirect superclass, and has the fields for all of them. The job of a class X constructor is to make the object being initialized capable of working as an X.
If there is no declared constructor, the compiler creates a parameterless constructor, so every class does have at least one constructor. If a constructor that is not the Object constructor does not start with a "this" or "super" constructor call, the compiler treats it as starting with "super();", a call to a parameterless constructor for the immediate superclass.
First line of each constructor in java calls super constructor, thats how java works.
You should read about it.
For example I have this:
class A{
private int mine = 0; //Some field...
public A(int a){mine+=a; /*Some operation1...*/}
}
class B extends A{
private int mine = 0; //Some field...
public B(int a){mine-=a; /*Some operation2...*/}
}
and I get:
error: constructor A in class A cannot be applied to given types;
public B(int a){}
required: int
found: no arguments
reason: actual and formal argument lists differ in length
1 errors
I don't understand the error? What is telling me to do?
Though, the code works if Constructor of "A" has no arguments. But I need to do the Operation1 (aka mine+=a;), so I need A's arguments, but then I fail.
I'm closed in this magic circle. What shall I do?
The first instruction of every constructor is always to invoke one of its superclass constructor. If you don't do it explicitely, the compiler inserts this instraction for you. The constructor
public B(int a) {
mine-=a;
/*Some operation2...*/
}
is thus equivalent to
public B(int a) {
super(); // invoke the no-arg super constructor
mine-=a;
/*Some operation2...*/
}
Since A doesn't have a no-arg constructor, the compilation fails. In this case, you must explicitely invoke one of the super constructors:
public B(int a) {
super(a);
mine-=a;
/*Some operation2...*/
}
Every constructor must call a superclass constructor as the first thing it does. If you do not do it explicitly via super(), the compiler will implicitly call the no-arts constructor in the superclass. But in your case, the superclass does not have a no-args constructor, at which point the compiler gives up.
By the way, it's generally a very bad idea to re-declare a field in a subclass, because it will hide the superclass field, but there will still be two fields.
I think you need to call class A's constructor from B constructor, like this:
super(a);
If B extends A, the first operation of the constructor of B is, to call the constructor of A.
If there is no constructor explicitly defined in A, the standard constructor is called. If you don't call the ctor explicitly, it is called implicitly.
But if there is an explicit ctor, which takes arguments, it isn't called automatically - how should it - with which arguments? You have to call it yourself.
But your class hierarchie is somewhat misterious. If you want to access mine in the subclass, make it protected or leave it in default state - don't make it private.
If you make it private, a new introduced attribute with the same name hides the parent attribute, but this is errorprone and irritating.
In most cases, access, maybe via a method (getter/setter), would be better, or opening the visibility.
Or a different name for the thing in the subclass.
While studying for my finals, I came across the following statement in the book from which I am currently studying. Considering the following code :
class A {
public A(int x) { }
}
class B extends A {
public B(int x ) { }
}
is it mandatory to call the constructor of class A in the constructor of class B(super(x)). The book states that it's not mandatory, because they have the exact number and type of parameters. But when I try this in a java compiler, the following error gets thrown :
constructor A in class A cannot be
applied to given types; required:
int found: no arguments reason:
actual and formal argument lists
differ in length
The compiler automatically inserts super() in the beginning.
However, even constructors arguments, super() (without arguments) is added which invokes the default constructor of the superclass. And you don't have one, hence the error.
You have to specify super(x) (to invoke A(x)), or define a no-argument constructor.
By the way, Eclipse compiler gives a way better error message:
Implicit super constructor A() is undefined. Must explicitly invoke another constructor
It looks like the compiler tries to create a call to the superclasses default constructor with super(), which isn't avaliable:
required: int
found: no arguments
But back to your book: I've never heard of a rule that you can skip the super statement in a constructor if the actual constructor has the exact same parameter list as a constructor in the direct superclass. Only a call to the superclass's default constructor is added implicitly (super()) but that requires that the superclass has a default constructor.
In contrast to what's written in your book (or in contrast to your understanding of the written text), here's a sentence from the 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 super
class constructor invocation “super();”, an invocation of the constructor of its
direct superclass that takes no arguments.
If you have a the base class having a default constructor (no-arg constructor), when you extend B, you don't need to explicitly call super() because it is called any way.
But when you have a constructor with arguments, when making the contructor with parameters in B, you need to pass in super() a parameter for A
example :
class A {
public A(int x) { }
}
class B extends A {
public B(int x )
{
super(x); // need to specify the parameter for class A
//...
}
}
This happens when you dont have a default constructor and you are creating an instance with default one. Because If you have any Parameterized constructor then compiler will not insert the default one for you, instead you have to define.
It is neccessary to call constructor of super class in case of Java. Therefore, whenever you generate constructor of sub class, super class' constructor is self created by IDE.
It is because whenever base class constructor demands arguments, compiler thinks they are to be filled by base class constructor. In case of default constructor, it is OK. No need to call super() in sub class.