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.
Related
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.
I have an abstract class and its concrete subclass, when I create an object of subclass it automatically calls the super constructor. Is the JVM internally creating an object of the abstract class?
public abstract class MyAbstractClass {
public MyAbstractClass() {
System.out.println("abstract default constructor");
}
}
public class ConcreteClass extends MyAbstractClass{
public static void main(String[] args) {
new ConcreteClass();
}
}
then how constructor exists without an object in JVM ?? (In case of abstract class)
Also constructor gets executed after object is being created then without creating the object of abstract class how the default constructor get executed ?? (This is mentioned in Java Doc)
Is it true that you can't instantiate abstract class?
Yes.
Is JVM internally create object of abstract class ?
No, but it's a common misunderstanding (and that wouldn't be an unreasonable way for it to be done; prototypical languages like JavaScript do it that way).
The JVM creates one object, which is of the class you created (in your case, ConcreteClass). There are aspects of that one object that it gets from its superclass (MyAbstractClass) and from its subclass (ConcreteClass), but there is only one object.
The object is an aggregate of all of its parts, including parts that seem to have the same name, such as a method of the superclass that is overridden by the subclass. In fact, those methods have different fully-qualified names and don't conflict with one another, which is why it's possible to call the superclass's version of an overridden method.
So if it's just one object, why do you see the call to MyAbstractClass's constructor? Before we answer that, I need to mention a couple of things the Java compiler is doing that you don't see in the source code:
It's creating a default constructor for ConcreteClass.
In that constructor, it's calling the MyAbstractClass constructor.
Just to be thorough: In the MyAbstractClass constructor, it's adding a call to the superclass's (Object) constructor, because there's no super(...) call written within the MyAbstractClass constructor.
Here's what the code looks like with the bits the Java compiler adds for you filled in:
public abstract class MyAbstractClass {
public MyAbstractClass() {
super(); // <== The Java compiler adds this call to Object's constructor (#3 in the list above)
System.out.println("abstract default constructor");
}
}
public class ConcreteClass extends MyAbstractClass{
ConcreteClass() { // <== The Java compiler adds this default constuctor (#1 in the list above)
super(); // <== Which calls the superclass's (MyAbstractClass's) constructor (#2 in the list above)
}
public static void main(String[] args) {
new ConcreteClass();
}
}
Okay, with that out of the way, lets touch on a point TheLostMind very usefully mentioned in a comment: Constructors don't create objects, they initialize them. The JVM creates the object, and then runs as many constructors (they really should be called initializers) against that one object as necessary to give each superclass a chance to initialize its part of the object.
So in that code, what happens (and you can step through this in a debugger to fully understand it) is:
The JVM creates an object
The ConcreteClass constructor is called
The first thing that constructor does is call its superclass's constructor, in this case MyAbstractClass's constructor. (Note that this is an absolute requirement: The Java compiler will not allow you to have any logic in the constructor itself prior to the superclass constructor call.)
The first thing that constructor does is call its superclass's constructor (Object's)
When the Object constructor returns, the remainder of the MyAbstractClass constructor runs
When the MyAbtractClass constructor returns, the remainder of the ConcreteClass constructor runs
The object is returned as the result of the new ConcreteClass() expression.
Note that the above would get more complicated if there were instance fields with initializers. See the JLS and JVM specs for the full details.
JVM doesn't create object of abstract class. it is calling its super constructor
JVM will create one object, an instance of the concrete class which inherits fields and methods of abstract class
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
The concept of shadowing
I am confused about how the fields of classes are handled in Java during upcasting. For example:
class SuperClass
{
String myString = "String in SuperClass";
public void myMethod()
{
System.out.println("Method in SuperClass");
}
}
class SubClass extends SuperClass
{
String myString = "String in SubClass";
public void myMethod()
{
System.out.println("Method in SubClass");
}
}
class Question
{
public static void main(String[] args)
{
SuperClass test = new SubClass();
// object test is an instance of SubClass
// but I am telling the compiler to treat it as SuperClass
test.myMethod();
System.out.println(test.myString);
}
}
Output:
Method in SubClass
String in SuperClass //Why is "String in SubClass" not used?
When I create an object test it is an instance of SubClass class; however, I am telling the compiler to treat it as SuperClass. Everything is clear to me about methods work: I will only be able to use the methods of the SubClass, if a given method is defined for SuperClass.
However, I am lost as to why a field of a SuperClass is used when I try to access myString of test. Since test is an instance of SubClass I would expect myString defined in SubClass to be used, why is this not happening? What am I missing?
I know that I can access, myString of SubClass by using this operator. For example, I could define printMyString method in SuperClass, and overwrite it with
public void printMyString()
{
System.out.println(this.myString);
}
In the SubClass, so my question is mostly about how come the field of the SuperClass is used in test. Maybe I am missing something obvious?
I tried to search for the answer, and the closest topic I found was Upcasting in Java and two separate object properties, though helpful, it did not answer my question.
Thank You in Advance
Attributes cant be overloaded like methods.
test.myMethod();
Here method invocation depends on the type of actual object. Here object is of type SubClass so method of SubClass is invoked.
test.myString
While accessing attributes,it depends on the type of reference variable. Here reference variable ie test is of type SuperClass so attribute from SuperClass is accessed.
What you are looking is class variable hiding / shadowing.
Fields in Java are only hidden and not actually overridden (that doesn't mean that we'll get a compile time error while trying this, instead they are not overridden in its true sense).
Overriding means the member should be invoked based on the run time
type of the object and not based on the declared type.
But binding for fields in Java is always static and hence it's based on the declared type of the object reference only.
In the example you've given, by declaring the class variable with the name 'myString' in class SubClass you hide the class variable it would have inherited from its superclass SuperClass with the same name 'myString'.
Java language specification :
If the class declares a field with a certain name, then the
declaration of that field is said to hide any and all accessible
declarations of fields with the same name in superclasses, and
superinterfaces of the class.
A hidden field can be accessed by using a qualified name if it is static, or by using a field access expression that contains the keyword super or a cast to a superclass type.
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