Calling of Constructors in a Java

2019-07-20 20:58发布

In the book Java: The complete reference

// Demonstrate when constructors are called.
// Create a super class.
class A {
     A() {
        System.out.println("Inside A's constructor.");
     }
}
// Create a subclass by extending class A.
class B extends A {
      B() {
             System.out.println("Inside B's constructor.");
      }
 }
// Create another subclass by extending B.
class C extends B {
    C() {
        System.out.println("Inside C's constructor.");
    }
}
class CallingCons {
    public static void main(String args[]) {
        C c = new C();
    }
}

Output: Inside A’s constructor Inside B’s constructor Inside C’s constructor

It is demonstrating how the constructor of a subclass is called. But why are constructors of the super class called in the absence of a super() constructor.

Why did the Java Language designers consider it necessary to do so?

7条回答
疯言疯语
2楼-- · 2019-07-20 21:12

As others have pointed out, if you don't start your constructor with a super(...) call, the compiler will put in a call to super() for you.

As to the why, you have to start with remembering what a constructor is for in the first place: initializing the object. What does that mean, specifically? In practice, it means assigning values to the object's fields, and establishing invariants.

Without a call to super(), the B and A classes wouldn't have a chance to do that for whatever fields they contain. And you can't even have the C() constructor do it for them, if those fields are private, since private fields aren't accessible outside your class (not even your super class's fields are accessible). Even if you could, it wouldn't be a good idea; it would also break encapsulation. For instance, imagine having to change your code if a super class -- possibly a complex one whose internals you're not an expert in -- suddenly decided to change its implementation details.

To illustrate this, consider a very simple set of classes:

public class Super {
    private final String name;

    Super() {
        name = "default";
    }

    public String name() {
        return name.toUpperCase();
    }
}

public class Sub extends Super {
    public Sub() {
        // don't do anything
    }
}

When you instantiate Sub, it will start out by calling Super's constructor. If it didn't, the name field would be null (the default value for reference types). But the name() method doesn't check for null; it assumes that the reference is non-null, because the constructor establishes that invariant. So, in our pseudo-Java that doesn't call the super constructor, Super.name has to get a bit more complicated -- it has to check for name == null.

You can imagine that as the classes gain more fields, with more interesting invariants, this toy example can become more and more complicated. Forcing you to call the super constructor -- either explicitly or implicitly -- lets the authors of that super class establish their invariants, resulting in simpler, more maintainable code.

查看更多
Emotional °昔
3楼-- · 2019-07-20 21:12

Because it says so in the Java Language Specification.

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.

查看更多
Emotional °昔
4楼-- · 2019-07-20 21:16

Even it has a role with Abstract classes also. we can't initialize object of abstract class. But Child class of Abstract class calls the super() method by default. So abstract class constructor can initialize its instance variables.
for example:

public abstract class TestA {

    private int a;
    public TestA()
    {
        a=10;
    }
    public int displayA()
    {
        return a;
    }

    abstract void display();

}
public class TestB extends TestA{

    @Override
    void display() {

       System.out.println("this is class B");

    }

}
package Abstract;

public class TestMain {


    public static void main(String[] args) {
        TestA obj= new TestB();
        System.out.println(obj.displayA());
    }
}

Output is : 10 Here you can see, when we initiating object of class TestB , by default super constructor is calling and TestA's constructor is assigning the value of a. If super will not be called by default we can't assign instance variables of abstract class.

查看更多
姐就是有狂的资本
5楼-- · 2019-07-20 21:22

"The Java programming language" says "A constructor in subclass can initialize its individual state, however, as keeping contract, only super class knows how to initialize super class's state".

Thus, constructor of super class have to be called. There is sequence how the constructor processed:

  • Call super class constructor
  • Initialize fields with initializers and initialization blocks
  • Execute body of the constructor

For more details, have a look of the book to section "3.2".

查看更多
淡お忘
6楼-- · 2019-07-20 21:23

Every constructor calls its superclass constructor. super() call take place as the first line in the constructor. From javadoc:

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.

more here

查看更多
我想做一个坏孩纸
7楼-- · 2019-07-20 21:24

Inheritance is basically inheriting all the properties of your parent class. So if a sub class constructor is called, it should definitely and by default inherit all its parent class properties also. In the following code, all the properties of class A should be made available in class B also, so if I just call B's constructor, all the class A's properties(except private) are also initialized and made available, meaning B has inherited A's properties

class A {
    protected int a;
    A() {
        a=12;
       System.out.println("Inside A's constructor.");
    }
}

class B extends A {
     B() {
            System.out.println("Inside B's constructor.");
            System.out.println(a);
     }
}

public class ConstructorInheritance {
   public static void main(String args[]) {
       B b=new B();
   }
}

output:
Inside A's constructor.
Inside B's constructor.
12
查看更多
登录 后发表回答