Does the JVM internally instantiate an object for an abstract class? - java

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

Related

Is my usage of a superclass constructor call here necessary?

I'm fairly new to Java and still practicing by basics with object-oriented design and programming. I have a few questions regarding inheritance, object creation, and the correct usage of a super() call.
Please consider the following:
Superclass,
package pet
public class Dog {
private String foodDogEats;
public Dog() {
this.foodDogEats;
}
public String getDogFood() {
return foodDogEats;
}
public void setDogFood() {
foodDogEats = "kibble";
}
}
subclass,
package pet
public class Fido extends Dog {
public Fido() {
super();
Dog dog = New Dog();
this.whatDoesFidoEat();
}
public whatDoesFidoEat(Dog dog) {
System.out.println("Fido eats " + dog.getDogFood());
}
}
and controller.
package pet
public class MyDogFido {
public void MyDogFido() {
Fido fido = new Fido();
}
}
The object in this example is, to instantiate a new Fido object and in the process of doing so perform the print behavior in whatDoesFidoEat(). I have a few questions -
Since I am already invoking a new Fido object (which is an extension of Dog, and if I recall correctly inherits its methods and variables), is instantiation of a new Dog object in the Fido() constructor redundant?
What about use of super()?
Which is the correct behavior - instantiating a Dog object in Fido(), calling super(), or both?
I initially wrote some similar code using both in the controlling class. After writing this question, though, my gut is telling me that I should only call super().
Feel free to comment on my sample code (particularly the this.foodDogEats; line in the Dog() constructor - also unsure about the usage there) as well.
Thanks!
You're right that the Dog dog = new Dog(); line is redundant. It would create a second, entirely separate Dog object.
The super() call is also unnecessary. All Java constructors implicitly call super() unless you override that behaviour by calling a different super-constructor.
Since I am already invoking a new Fido object (which is an extension of Dog, and if I recall correctly inherits its methods and variables), is instantiation of a new Dog object in the Fido() constructor redundant?
It is not redundant per se, but it is rather pointless and wasteful. You are instantiating a new, different Dog, and then ignoring it. The garbage collector will eventually clean it up, but you never needed it in the first place. Your Fido, which you can refer to inside the class constructor and methods as this, is a Dog. You do not need to do anything in the constructor to make that be so, and you cannot do anything in the constructor to prevent it from being so.
What about use of super()?
If a class's constructor does not explicitly invoke either another constructor of the same class or one of the superclass's constructors, then it implicitly invokes super(). In that case, if the superclass has no such nullary constructor then that is an error. It is not exactly redundant to explicitly invoke super() because that suppresses the implicit invocation, but it is not necessary to do so.
Which is the correct behavior - instantiating a Dog object in Fido(), calling super(), or both?
You initialize the superclass by directly or indirectly invoking one of its constructors. That invocation can be implicit if the superclass has a nullary constructor, and if that's the one you want to invoke.
Feel free to comment on my sample code (particularly the this.foodDogEats; line in the Dog() constructor - also unsure about the usage there) as well.
The line you reference is erroneous. If it were allowed, I would expect it to evaluate to the default value of this.foodDogEats (null), with no other effect. That would be pretty pointless.
Additionally, your setDogFood() method is odd. A property setter would normally have this form:
public void setDogFood(String what) {
foodDogEats = what;
}
Your original version is kinda pointless.
your code should show a compiler error in the superclass.
Let's run through the logic you have:
In the super class you have
this.foodDogEats; // should be a compiler error
What do you think it does? It does nothing because it is just a statement. The 'this' keyword only means you are referring to the variable in the specific instance of the object that you created but you do nothing with it which leads to the error.
In your subclass, you do not need to call super since super is called automatically by default unless you do not have a no argument constructor in the super class.
If a constructor does not explicitly invoke a superclass constructor, then 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.
Your use of super() is correct.
Your use of a Dog object is completely unnecessary.
By extending Dog, Fido inherits the non-private fields and method of Dog. Therefore, you can simplify Fido:
package pet;
public class Fido extends Dog {
//Since this is a default constructor (no args and super() only),
//you don't even have to declare this.
public Fido() {
super();
}
public void whatDoesFidoEat() {
System.out.println("Fido eats " + foodDogEats);
}
}
And then, simplify your use of it:
package pet;
public class MyDogFido {
public void MyDogFido() {
Fido fido = new Fido();
//This is a setter method for your foodDogEats. It should be declared in Dog.
fido.setFoodDogEats("Beggin' Strips");
fido.whatDoesFidoEat();
}
}
You can still have your Fido() constructor call whatDoesFidoEat, but since creation of the object doesn't seem dependent on the method, I find it better practice to avoid calls like that in the constructor.
Edit:
If you wanted to define foodDogEats upon construction, you could define a constructor Fido(String):
public Fido(String foodDogEats) {
this.foodDogEats = foodDogEats;
}
Or if your foodDogEats is dependent on the class rather than the instance, and never changes, you could make the variable public static final FOOD_DOG_EATS. Be careful - accessing it via Fido.FOOD_DOG_EATS will be different than Dog.FOOD_DOG_EATS because static variables are not inherited.

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.

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