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?
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.
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
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.
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.
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
Imagine class C accessing an unitialized variable of class B or A. Implicitly calling constructors of class B-->class A makes sure that you are always accessing initialized variables of inherited classes(A or B)
"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".
Related
Why is the constructor in B required?
IntelliJ suggests to remove =null as it is redundant presumably because it is initialized through the given constructor in A.
However, this removal (which is presumably also performed by the compiler) then (presumably) requires the constructor in B.
Any other explanation?
public abstract class A {
private Object foo = null;
public A(Object foo){this.foo=foo;}
}
public class B extends A {
public B(Object foo){super(foo);}
}
Java does not have "constructor inheritance". The only way to initialize A is to pass the foo parameter to its constructor, and the only way to do this is to create a constructor for B that does so.
Note, however, that they don't have to have the same signature (like you have in the question) - B's constructor only needs to pass some parameter to A. E.g.:
public class B extends A {
public B() {
super("Arbitrary default passed to A");
}
public B(Object passedToA, Obejct notPassedToA) {
super(passedToA);
System.out.println("This argument was not passed to A():" + notPassedToA);
}
}
Why is the constructor in B required?
If the class B extends A, the class B must be instantiated in all possible ways as the class A can be and the class B can have additional ways to be instantiated. It means that class B is forced to have a constructor.
The only exemption can be in case of a no-arg constructor because the compiler makes it up with a default constructor i.e. if you put a no-arg constructor in the class A the child classes are not forced to have this.
I'm having trouble understanding the concept of using constructors with subclasses.
Here is the parent class:
public class A
{
public A()
{
System.out.println("The default constructor of A is invoked");
}
}
The child class:
public class B extends A
{
public B(String s)
{
System.out.println(s);
}
}
And my main method:
public class C
{
public static void main (String[] args)
{
B b = new B("The constructor of B is invoked");
}
}
When I run C, the output I get is
The default constructor of A is invoked
The constructor of B is invoked
What I don't understand is why the message from class A is getting output. Because you pass in a string argument to the constructor of the B class, shouldn't it just print out s? In other words, shouldn't the output simply be:
The constructor of B is invoked
Thanks in advance, I really appreciate any help you guys can give.
From the docs
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.
So even though you've not explicitly called the super class constructor, the compiler inserts a statement called super() in the constructor of class B.
This is how the class B constructor would look post compilation.
public B(String s){
super(); // this is inserted by the compiler, if you hadn't done it yourself.
System.out.println(s);
}
After compilation class B -
public class B extends A{
public B(String s){
super();
System.out.println(s);
}
}
And why! logical answer is child can not be existed without parent, so parent is initialized fast then child.
Technically - if you do not explicitly invoke super class constructor compiler will do it for you. what exactly happened in your case.
A good experiment would be if you invoke the super class contructor explicitly which help you understand this more closely-
public class B extends A{
public B(String s){
System.out.println(s);
super(); // invoking super later
}
}
you get an compilation error -
error: call to super must be first statement in constructor
So In case you are explicitly invoking the super class constructor, then you have to invoke at the start of constructor which should be first statement.
The reason it does this is that B needs to have all the fields in A if B is indeed a subclass of A. Therefore, when you call the constructor
B b = new B("The constructor of B is invoked");
It calls the default constructor of A to initialize A's fields, thus B is actually logically doing
public class B extends A
{
public B(String s)
{
super();
System.out.println(s);
}
}
where super just calls A's default constructor. If the compiler did not do this, you would have uninitialized fields in B since it inherits from A!
Does JVM call default Constructor of Anonymous Class to create instance.
My understanding may be stupid for that. I think, even if Reflection API is used to create an instance, there will be at least Default Constructor. Anonymous Class have a Default Constructor? Otherwise, how JVM or whatever create instance?
Yes it does. You can even use other constructors through specifying parameters:
Given
public abstract class A {
String str;
public A(String str){
this.str=str;
}
public abstract void doSomething();
}
You can do
...
A a = new A("Hello World") {
public void doSomething() {
System.out.println(str);
}
};
a.doSomething();
When a class doesn't have an explicit constructor, it has an implicit default empty constructor. That is called, just as any other constructor would be called.
It appears to me that unlike normal classes, anonymous classes has different behaviour associated with implicit constructors.
When you define a normal class, compiler can implicitly insert only a no-arg constructor.
But with anonymous class you can get (implicitly by a compiler) all the constructors the superclass has.
Say we have a class:
class A {
A(int i) {}
A(String s) {}
}
If we subclass it as follows...
class B extends A {}
...we get a compilation error because compiler tries to do this:
class B extends A {
B() {
super(); // Error: there's no no-arg superclass constructor!
}
}
But when we create an anonymous class it implicitly creates constructors as defined for a superclass (A)
A a1 = new A(1) {}; // OK. Uses (int) constructor
A a2 = new A("") {}; // OK. Uses (String) constructor
A a3 = new A() {}; // Error. There's no no-arg constructor
As if our anonymous class has these constructors
X(int i) {
super(i);
}
X(String s) {
super(s);
}
Anonymous classes have a default no args constructor that is called once by the JVM. Since an anonymous class has no name, it is not possible to define a constructor for an anonymous class. If your class requires a constructor, you must use a local class instead.
In any case, a constructor is called to initialize newly created object. Anonymous class has default constructor, which initialize the fields of the class, if any, and calls constructor of the superclass.
I'm dealing with a class which extends JFrame.
It's not my code and it makes a call to super before it begins constructing the GUI. I'm wondering why this is done since I've always just accessed the methods of the superclass without having to call super();
There is an implicit call to super() with no arguments for all classes that have a parent - which is every user defined class in Java - so calling it explicitly is usually not required. However, you may use the call to super() with arguments if the parent's constructor takes parameters, and you wish to specify them. Moreover, if the parent's constructor takes parameters, and it has no default parameter-less constructor, you will need to call super() with argument(s).
An example, where the explicit call to super() gives you some extra control over the title of the frame:
class MyFrame extends JFrame
{
public MyFrame() {
super("My Window Title");
...
}
}
A call to your parent class's empty constructor super() is done automatically when you don't do it yourself. That's the reason you've never had to do it in your code. It was done for you.
When your superclass doesn't have a no-arg constructor, the compiler will require you to call super with the appropriate arguments. The compiler will make sure that you instantiate the class correctly. So this is not something you have to worry about too much.
Whether you call super() in your constructor or not, it doesn't affect your ability to call the methods of your parent class.
As a side note, some say that it's generally best to make that call manually for reasons of clarity.
None of the above answers answer the 'why'.
Found a good explanation here:
A subclass can have its own private data members, so a subclass can
also have its own constructors.
The constructors of the subclass can initialize only the instance
variables of the subclass. Thus, when a subclass object is
instantiated the subclass object must also automatically execute one
of the constructors of the superclass.
You might also want to read everything about the super keyword here or watch everything about the super keyword here.
We can access super class elements by using super keyword
Consider we have two classes, Parent class and Child class, with different implementations of method foo. Now in child class if we want to call the method foo of parent class, we can do so by super.foo(); we can also access parent elements by super keyword.
class parent {
String str="I am parent";
//method of parent Class
public void foo() {
System.out.println("Hello World " + str);
}
}
class child extends parent {
String str="I am child";
// different foo implementation in child Class
public void foo() {
System.out.println("Hello World "+str);
}
// calling the foo method of parent class
public void parentClassFoo(){
super.foo();
}
// changing the value of str in parent class and calling the foo method of parent class
public void parentClassFooStr(){
super.str="parent string changed";
super.foo();
}
}
public class Main{
public static void main(String args[]) {
child obj = new child();
obj.foo();
obj.parentClassFoo();
obj.parentClassFooStr();
}
}
It simply calls the default constructor of the superclass.
We use super keyword to call the members of the Superclass.
As a subclass inherits all the members (fields, methods, nested classes) from its parent and since Constructors are NOT members (They don't belong to objects. They are responsible for creating objects), they are NOT inherited by subclasses.
So we have to explicitly give the call for parent constructor so that the chain of constructor remains connected if we need to create an object for the superclass. At the time of object creation, only one constructor can be called. Through super, we can call the other constructor from within the current constructor when needed.
If you are thinking why it's there for a class that is not extending any other class, then just remember every class follows object class by default. So it's a good practice to keep super in your constructor.
Note: Even if you don't have super() in your first statement, the compiler will add it for you!
We can Access SuperClass members using super keyword
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged). Consider this class, Superclass:
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
// Here is a subclass, called Subclass, that overrides printMethod():
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
Within Subclass, the simple name printMethod() refers to the one declared in Subclass, which overrides the one in Superclass. So, to refer to printMethod() inherited from Superclass, Subclass must use a qualified name, using super as shown. Compiling and executing Subclass prints the following:
Printed in Superclass.
Printed in Subclass
as constructor is not a part of class,
so while calling it cannot be implemented,
by using SUPER() we can call the members and memberfunctions in constructor.
Why default constructor is required(explicitly) in a parent class if it has an argumented constructor
class A {
A(int i){
}
}
class B extends A {
}
class Main {
public static void main(String a[]){
B b_obj = new B();
}
}
This will be an error.
There are two aspects at work here:
If you do specify a constructor explicitly (as in A) the Java compiler will not create a parameterless constructor for you.
If you don't specify a constructor explicitly (as in B) the Java compiler will create a parameterless constructor for you like this:
B()
{
super();
}
(The accessibility depends on the accessibility of the class itself.)
That's trying to call the superclass parameterless constructor - so it has to exist. You have three options:
Provide a parameterless constructor explicitly in A
Provide a parameterless constructor explicitly in B which explicitly calls the base class constructor with an appropriate int argument.
Provide a parameterized constructor in B which calls the base class constructor
Every subclass constructor calls the default constructor of the super class, if the subclass constructor does not explicitly call some other constructor of the super class. So, if your subclass constructor explicitly calls a super class constructor that you provided (with arguments), then there is no need of no arguments constructor in the super class.
So, the following will compile:
class B extends A{
B(int m){
super(m);
}
}
But the following will not compile, unless you explicitly provide no args constructor in the super class:
class B extends A{
int i;
B(int m){
i=m;
}
}
Why default constructor is required(explicitly) in a parent class if it has an argumented constructor
I would say this statement is not always correct. As ideally its not required.
The Rule is : If you are explicitly providing an argument-ed constructer, then the default constructor (non-argumented) is not available to the class.
For Example :
class A {
A(int i){
}
}
class B extends A {
}
So when you write
B obj_b = new B();
It actually calls the implicit constructor provided by java to B, which again calls the super(), which should be ideally A(). But since you have provided argument-ed constructor to A, the default constructor i:e A() is not available to B().
That's the reason you need A() to be specifically declared for B() to call super().
Assuming that you meant to write class B extends A:
Every constructor has to call a superclass constructor; if it does not the parameterless superclass constructor is called implicitly.
If (and only if) a class declares no constructor, the Java compiler gives it a default constructor which takes no parameters and calls the parameterless constructor of the superclass. In your example, A declares a constructor and therefor does not have such a default constructor. Class B does not declare a constructor, but cannot get a default constructor because its superclass does not have a parameterless constructor to call. Since a class must always have a constructor, this is a compiler error.
Why default constructor is required(explicitly) in a parent class if it
has an argumented constructor
Not necessarily!
Now in your class B
class B extends A {
}
you have not provided any constructor in Class B so a default constructor will be placed. Now it is a rule that each constructor must call one of it's super class constructor. In your case the default constructor in Class B will try to call default constructor in class A(it's parent) but as you don't have a default constructor in Class A(as you have explicitly provided a constructor with arguments in class A you will not have a default constructor in Class A ) you will get an error.
What you could possibly do is
Either provide no args constructor in Class A.
A()
{
//no arg default constructor in Class A
}
OR
Explicitly write no args constructor in B and call your super with some default int argument.
B()
{
super(defaultIntValue);
}
Bottom line is that for an object to be created completely constructors of each parent in the inheritance hierarchy must be called. Which ones to call is really your design choice. But in case you don't explicitly provide any java will put default constructor super() call as 1st line of each of your sub class constructors and now if you don't have that in superclass then you will get an error.
There are a few things to be noted when using constructors and how you should declare them in your base class and super class. This can get somewhat confusing solely because there can be many possibilities of the availability or existence of constructors in the super class or base class. I will try to delve into all the possibilities:
If you explicitly define constructors in any class(base class/super class), the Java compiler will not create any other constructor for you in that respective class.
If you don't explicitly define constructors in any class(base class/super class), the Java compiler will create a no-argument constructor for you in that respective class.
If your class is a base class inheriting from a super class and you do not explicitly define constructors in that base class, not only will a no-argument constructor be created for you (like the above point) by the compiler, but it will also implicitly call the no-argument constructor from the super class.
class A
{
A()
{
super();
}
}
Now if you do not explicity type super(), (or super(parameters)), the compiler will put in the super() for you in your code.
If super() is being called (explicitly or implicitly by the compiler) , the compiler will expect your superclass to have a constructor without parameters. If it does not find any constructor in your superclass without parameters, it will give you a compiler error.
Similary if super(parameters) is called, the compiler will expect your superclass to have a constructor with parameters(number and type of parameters should match). If it does not find such a constructor in your superclass, it will give you a compiler error. ( Super(parameters) can never be called implicitly by the compiler. It has to be explicitly put in your code if one is required.)
We can summarize a few things from the above rules
If your superclass only has a constructor with parameters and has no no-argument constructor, you must have an explicit super(parameters) statement in your constructor. This is because if you do not do that a super() statement will be implicitly put in your code and since your superclass does not have a no-argument constructor, it will show a compiler error.
If your superclass has a constructor with parameters and another no-argument constructor, it is not necessary to have an explicit super(parameters) statement in your constructor. This is because a super() statement will be implicitly put in your code by the compiler and since your superclass has a no-argument constructor, it will work fine.
If your superclass only has a no-argument constructor you can refer to the point above as it is the same thing.
Another thing to be noted is if your superclass has a private constructor, that will create an error when you compile your subclass. That is because if you don't write a constructor in your subclass it will call the superclass constructor and the implicit super() will try to look for a no-argument constructor in the superclass but will not find one.
Say this compiled, what would you expect it to print?
class A{
A(int i){
System.out.println("A.i= "+i);
}
}
class B extends A {
public static void main(String... args) {
new B();
}
}
When A is constructed a value for i has to be passed, however the compiler doesn't know what it should be so you have specify it explicitly in a constructor (any constructor, it doesn't have to be a default one)
Of course its an error if written like this it's not JAVA.
If you would have use JAVA syntax it wouldn't be an error.
Class A and B knows nothing about each other if in separate files/packages.
Class A doesn't need a default constructor at all it works fine with only a parameter constructor.
If B extends A you simple use a call to super(int a) in B's constructor and everything is fine.
for constructors not calling a super(empty/or not) extending a super class the compiler will add a call to super().
For further reading look at Using the Keyword super
I would guess that its because when you have an empty parameter list the super variable can't be instantiated. With empty parameter list I mean the implicit super() the compiler could add if the super class had a nonparametric constructor.
For example if you type:
int a;
System.out.print(a);
You will get an error with what I think is the same logic error.
When we have parameter constructor. we explicit bound to consumer by design. he can not create object of that class without parameter. some time we need to force user to provide value. object should be created only by providing parameter(default value).
class Asset
{
private int id;
public Asset(int id)
{
this.id = id;
}
}
class Program
{
static void Main(string[] args)
{
/* Gives Error - User can not create object.
* Design bound
*/
Asset asset1 = new Asset();/* Error */
}
}
Even child class can not create. hence it is behavior of good design.
When extending a class, the default superclass constructor is automatically added.
public class SuperClass {
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
//super(); <-- Java automatically adds the default super constructor
}
}
If you've overloaded your super class constructor, however, this takes the place of the default and invoking super() will thus cause a compile error as it is no longer available. You must then explicitly add in the overloaded constructor or create a no-parameter constructor. See below for examples:
public class SuperClass {
public SuperClass(String s, int x) {
// some code
}
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
super("some string", 1);
}
}
OR...
public class SuperClass {
public SuperClass() {
// can be left empty.
}
}
public class SubClass extends SuperClass {
public SubClass(String s, Product... someProducts) {
//super(); <-- Java automatically adds the no-parameter super constructor
}
}
Because if you want to block creation of objects without any data in it, this is one good way.