Behavior when a Subclass doesn't invoke superclass constructor - java

According to my text book:
If the execution of any constructor in a subclass does not invoke a
superclass constructor, Java automatically invokes the no-parameter
constructor for the superclass.
Does that mean all the superclass data field(superclass variables) would be set to null(because the constructor is a no-parameter constructor)?

No, if the supers constructor with no arguments initializes some objects - this initialization will be done.
class A {
public int x;
A () {
x = 1;
}
}
class B extends A {
B() {
}
}
The B's constructor will still invoke super() as the first line (even though it is not explicitly written), and will initialize x=1 in the process.

No:
class A {
public int x;
public A() {
x = 42;
}
}
class B extends A {}
assert(new B().x == 42)
The "no-parameter constructor" does not have to be an empty constructor.

It means that superclass's fields will be set to whatever the non-parameter constructor sets them.
This may or may not be null. If the non-parameter superclass constructor is not defined and if the subclass's constructor doesn't set the superclass fields, then yes they will be null.

if the person is careless and doesn't specify them, would we get an error?
You haven't said what "them" refers to, but ...
If a class constructor relies (explicitly or implicitly) on a no-args constructor that its superclass does not provide (explicitly or implicitly), then that is a compilation error.
If the programmer accidentally leaves out the constructors in a class and its reference fields are (only) default initialized to null as a result, you won't get a compilation error. (The code is valid. The compiler cannot determine the intent of the programmer; i.e. whether the constructor was omitted accidentally or deliberately.) But you may get a runtime error later on if some code uses the field / field value assuming it to be non-null.
If the programmer defines a constructor but the constructor fails to initialize some field, then the outcome is that same as 2. No compilation error, and possible runtime error.

Related

What is the actual use of the default constructor in java?

I have read in many sources and books that constructor is used to initialise the fields when an object is created. I have also read that JVM provides a default constructor if I don't mention one. What is the purpose of a constructor if it is not required to initialise the fields like the one I have mentioned below?
I also understand that a constructor without parameter is required as
it is necessary during object creation when an argument is not passed
(when programmer-defined constructors with parameters exists).
Is it necessary for JVM to provide a constructor which is actually not required?
public class test {
int a;
public test() {
//this constructor is useless
}
public static void main(String[] args)
{
test ob= new test();
System.out.println(ob.a);
//this prints 0 which means a constructor is not required in intialising `a`
}
}
A constructor like test() makes sense if the programmer defines it since there could be other constructors which takes argument.
But why is it necessary for JVM to provide one when no constructor is declared by the programmer?
I have already tested and proved that initialising a field doesn't require constructor.
Also what does the default constructor look like?
The problem is that while you know the default constructor doesn't do anything in this example, in future the constructor might do something even if you don't realise it is and you might not be able to re-compile everywhere the code is used reliably. So the safest, simplest thing to do is to always call a constructor which might change in the future and let the JIT optimise away the constructor if it doesn't actually do anything.
The byte code always calls a contructor, whether you provide one or not. When you compile code which uses the default constructor it cannot assume the constructor doesn't do anything useful as you can add something to it later to do something useful. e.g.
Say you change
public class Test {
int a;
// public Test() { //this constructor does nothing
}
to
public class Test {
int a;
final List<String> strings = new ArrayList<>();
// public Test() { //this constructor does something now.
}
or
public class ServerTest {
final List<String> strings = new ArrayList<>();
}
public class Test extends SuperTest {
int a;
// the default constructor has to call super();
}
The constructor now initialised the strings field. You can change this class without having to re-compile everywhere it is used and say, hey, my constructor now does something useful, you should call it now.
The reason the JVM adds a default constructor if you haven't provided one is down to inheritance. Say for example you have 3 classes (A, B & C) in which B extends A and C extends B. Now when you instantiate C it will call the constructor of C and also the constructors of B and A. If a constructor was missing in one or more of these classes then the instantiation would fail. So having the compiler automatically add a default constructor avoids error like this. You may not need to actually do any work in your constructor, but it's required for the JVM to instantiate the object.
The constructor(s) (both default and custom one(s)) is not only used to initialize the fields of an object but also to initialize the object itself even if it has no fields at all. Calling the constructor, JVM allocates memory for this object and creates its reference.
It is the compiler, and not JVM, who inserts a default constructor on absence.
A default constructor is needed because the constructor of the base class needs to be called from a constructor.
The default constructor looks like:
public Test() {
super();
}
Here while you are creating the object new test(),
here parenthesis states the default constructor of object test.After creating the object,if you didnot give any constructor the default constructor is constructed by jvm.so after construction of your object first call goes to your default constructor.
The default constructor is a no argument constructor called automatically by the compiler when you haven't defined any constructor. Anyway, a constructor as the one you defined, can be also called a default constructor.
It basically calls the superclass' constructor making use of the super() method.
So the default constructor called automatically would be something like:
public ClassName(){
super();
}
Java's Compiler creates a Default Constructor if no other constructor is defined for the class.
But why?
The compiler's job is to chain the Subclass's constructor to the Super Class(ultimately Object class). It's not the Compiler's work to give a default constructor to your class therefore Java is doing it for you.
To do the chaining, it first checks if there is any constructor in the class, if yes it will add super() to that constructor.
If there is no constructor idefined in the class in order for the compiler to do a proper chaining, Java adds a default constructor and a call to super() into it.
Why ?
Because every class is a subclass of an Object class (directly or indirectly), it will inherit an object class, to do so the said Object class must be fully initialised. This is done by the default constructor.

Order of Constructors execution in derived class in Java

I have derived a class in java.
I noticed that the superclass constructor gets called before code in my derived class constructor is executed.
Is there a way to invert that order?
Example:
class Animal
{
public Animal()
{
//do stuff
}
}
class Cat extends Animal
{
int var;
public Cat(int v)
{
var = v;
super();
}
}
This is what I would like to do, but calling super() like that gives an error...
No, there is no way to invert that order. If you explicitly call a parent class constructor you are required to do it at the top of your constructor. Calling it later would allow a child class to access the parent class's data before it's been constructed.
No, you can't invert the order of constructor calls this way. A call to super() must be the first statement in a constructor. And if there is no such call, Java inserts an implicit call to super() as the first statement.
The JLS, Section 8.8.7, states:
The first statement of a constructor body may be an explicit invocation of another constructor of the same class or of the direct superclass (ยง8.8.7.1).
ConstructorBody:
{ [ExplicitConstructorInvocation] [BlockStatements] }
There isn't a way to call run the sub class constructor before superclass constructor. That's basically like trying to create the subclass even before the superclass gets created, which is impossible since the subclass relies on superclass attributes to get created.

Default constructor can be overloaded in a subclass? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This is question (and answer) from OCJP test exam. And I was very confused about it.
Here is a question review (on Kaplan SelfTest site):
Reviewing Answered
Item 64 of 90Ref: 1Z0-803.6.5.6
Which statement is true about constructor overloading?
A default constructor can be overloaded in the same class.
A default constructor can be overloaded in a subclass.
The constructor must use a different name.
The constructor must use the this keyword.
Explanation:
A default constructor can be overloaded in a subclass. If no constructor is defined for a class, then the compiler will automatically provide the default constructor. Because a subclass can define its own constructors without affecting the superclass, a constructor with parameters can be defined that invokes the superclass constructor, implicitly or explicitly.
A default constructor cannot be overloaded in the same class. This is because once a constructor is defined in a class, the compiler will not create the default constructor. Thus, an attempt to overload the default constructor will effectively remove it from the class.
The constructor must not use a different name. In the same class, an overloaded constructor uses the same name. Because subclasses differ in name from their superclass, an overloaded constructor will have a different name.
The constructor does not need to use the this keyword. The this keyword allows a constructor to reference other constructor methods and/or instance context. Using the this keyword is not required in an overloaded constructor.
Objective:
Working with Methods and Encapsulation
Sub-Objective:
Create and overload constructors
You are getting your terminology wrong.
Overloading only takes place for methods with the same name but different parameters within a specific class.
Overriding takes place for subclasses which have methods with the same "signature" (same name and parameters) as a method in the Superclass.
Note that constuctors aren't "Overridden" (by definition they have different signatures than methods in the superclass).
Instead, the compiler makes a constructor implicitly call the default constructor of its superclass (if one exists) unless you explicitly call a specific constructor of a superclass using the super keyword.
Similarly you cannot "Overload" the constructor of a superclass in a subclass (overloading doesn't work across inheritance), but you can "overload" another constructor within your specific class.
Here is an example of implicit and explicit calls to superclass constructors and overloading constructors:
public class X {
// no default constructor defined so
// compiler adds implicit default constructor here: public X(){}
}
public class Y extends X {
// explicitly declared default-constructor for class Y
public Y() {
// compiler automatically calls implicit X default constructor here
System.out.println("constructing a Y instance");
}
// explicitly declared constructor which overloads the default constructor for Y
public Y(String s) {
// compiler automatically calls implicit X default constructor here
System.out.println("constructing a Y instance with param " + s);
}
}
public class Z extends Y {
// explicitly declared default constructor for Z
public Z() {
super("Z"); // explicitly call the non-default constructor in Y here
System.out.println("constructing a Z instance");
}
}
thus constructing a Z ends up calling X(), then Y("Z") and results in this output:
Z z = new Z();
// outputs: constructing a Y instance with param Z
// constructing a Z instance
And from the docs: (http://docs.oracle.com/javase/tutorial/java/IandI/super.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. If the super class does not have a no-argument constructor, you will get a compile-time error.
Hope that helps clarify things for you. If in doubt read the docs, write some code, and use System.out.println() to see what's happening.
Constructors are not technically member functions, so they aren't really inherited, and thus cannot be "overloaded". However, they can still be called from the subclass using the super keyword.
//the class being inherited
public class superclass
{
//the constructor
public superclass(some_parameter)
{
//do stuff
}
}
public class subclass extends superclass
{
public subclass(some_parameter)
{
//the super keyword here is used to access the inherited class
super(some_parameter); //this calls the constructor of the inherited class;
}
}
First, overload is not the same as override. Example:
class Foo {
void overloadedMethod() {}
void overloadedMethod(int i) {}
void overridenMethod() {}
}
class Bar extends Foo {
#Override
void overridenMethod() {}
}
Constructor can be overloaded, just as ordinary methods, but cannot be overriden.
For more info see here: link

When is mandatory to have a default constructor along with parameterized constructor in Java?

Many a time I have got an exception saying "the default constructor's implementation is missing". And many a times a parameterized constructor's definition alone does everything. I want to know under which conditions this happens.
If there is no Constructor present in a class, one Default Constructor is added at Compile time.
If there is any one parametrized Constructor present in a class, Default Constructor will not be added at Compile time.
So if your program has any constructor containing parameters and no default constructor is specified then you will not be able to create object of that class using Default constructor.
Eg:
class A{
A(int a){}
}
A a = new A() -----> Error.
-------------------------------------------------------
class A{
A(int a){}
A(){}
}
A a = new A() -----> It will work.
-----------------------------------------------------------
class A{
}
A a = new A() -----> It will work.
The compiler doesn't ever enforce the existence of a default constructor. You can have any kind of constructor as you wish.
For some libraries or frameworks it might be necessary for a class to have a default constructor, but that is not enforced by the compiler.
The problem you might be seeing is if you have a class with a custom constructor and you don't have an implicit super() call in your constructor body. In that case the compiler will introduce a call to the super classes default constructor. If the super class doesn't have a default constructor then your class will fail to compile.
public class MyClass extends ClassWithNoDefaultConstructor
public MyClass() {
super(); //this call will be added by the compiler if you don't have any super call here
// if the super class has no default constructor the above line will not compile
// and removing it won't help either because the compiler will add that call
}
}
AS Joachim Sauer said, its important/some times required to provide default constructor apart from your parametrized constructor when you are using frameworks like spring. Because if you want inject your class object through dependency injection in another class, then the class should have default constructor.
Otherwise your dependency injection will fail.
Its just one scenario where i encountered the importance of default constructor
It is not entirely clear whether you are talking about a runtime exception or a compilation error.
A runtime exception will only occur if your code (or some library code called by your code) attempts to use reflection to create an instance of some class, and accidentally tries to use a non-existent constructor. (And I doubt that the exception message would use the term "default constructor" ...)
A compilation error happens because you are explicitly or implicitly attempting to call a "no args" constructor that does not exist. There are three scenarios'
// case #1
new Foo();
// case #2
public Bar extends Foo {
public Bar() {
super();
}
}
// case #3
public Bar extends Foo {
public Bar() {
// no explicit 'this' or 'super' call.
}
}
The first two examples are pretty obviously invoking a no-args constructor.
The last example invokes the no-args constructor because if you don't have an explicit super or this "call" at the start of a constructor, the JLS says that a call to super() will occur ... in all cases apart from the constructor for Object.
Finally, you answer the question in the title:
When is mandatory to have a default constructor along with parameterized constructor in Java?
Strictly speaking, it is never mandatory to have a default constructor. It is mandatory to have a no args constructor (either explicitly declared, or default) ... only if it is explicitly or implicitly called.
(There could be libraries / frameworks that assume that your classes have no-args constructors, but that is beyond the scope of what we can answer. And besides, such an assumption will be so that instances can be created reflectively ... and I've covered that.)
In general this situation can be happen when instance of class is creating by reflection (for example while de-serializing). If your class is Serializable or instance of it can be created by reflection mechanism, you should define default constructor.
case 1:
If you don't write a constructor then default constructor
will be added (by compiler) and you can create object using it. But
if you write a parameterised constructor, and want to create object
like
ClassName ObjName = new ClassName();
then you have to add default constructor manually.
case 2(Inheritances): If your childclass constructor do not make a
explicit call to parentclass constructor (in first line itself), then
compiler will do it for you.
class ChildClass extends ParentClass{
ChildClass(){
//super() added by compiler.
}
}
Now same thing,
if no constructor in parentclass, fine Default Constructor (added by compiler) will be called.
but if parentclass has a parameterised constructor, then there is no default constructor and so you get your error.
Its mandatory when you have a Parameterised constructor and
want to create object like case 1.
inherit this class and do not make a explicit call
super(parameter,...);
in first line of ChildClass constructor.
Compiler will add default constructor when code is compiled but when you declared a parameterized constructor in code, default constructor will be omitted.
When default constructor is overloaded with parameterized constructor, It is necessary to have a default constructor in code when you create object using default constructor instead of parameterized constructor.
There is a need of default constructor when you are using a framework (example: Spring framework) where you need to create instances of Spring bean and the bean class has only the parameterized constructor.
#Component
public class Bank {
private String bankName;
public Bank(String bankName){
this.bankName = bankName;
}
#Override
public String toString() {
return this.bankName;
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext context = new
AnnotationConfigApplicationContext(SpringConfig.class);
Bank bank = context.getBean(Bank.class);
System.out.println(bank);
}
}
will throw an error asking to implement default constructor

What does "constructors are not inherited" exactly mean?

I read somewhere that in Java "constructors are not inherited".
On the other hand, I also read that if I don't explicitly call super, Java automatically calls the super class constructor with no arguments (such a constructor must exist in this case).
Isn't automatically calling the super class constructor (with no arguments) a form of inheritance?
What does "constructors are not inherited" exactly mean?
It means that you cannot create a subclass, using a constructor of the super class-if the subclass did not also declared it. An example;
class A {
A() {}
A(String s) {}
}
class B extends A {
}
Now you cannot do this:
B b = new B("testing");
It means just because your superclass has a contructor doesn't mean the subclass will automatically get the same constructor; you have to define it manually.
The default constructor is kind of an exception and kind of isn't. It's automatically defined for you, but it's not really "inherited" because it's still part of the subclass; it's not a member of the superclass.

Categories