I have seen many threads (e.g.: Inheritance in Java - creating an object of the subclass invokes also the constructor of the superclass. Why exactly?) saying that the instance of superclass will NOT be created when creating a subclass instance. I actually agree with this opinion.
However, I can't find any official materials (from Oracle) to back this up. I searched a couple of hours and cannot find anything. Can anyone refer me to a reliable resource to confirm this?
When an instance of a derived class is created the heap allocation will be something like (*):
- Standard JVM object header (with pointer to Class object for
DerivedClass
)
- Instance fields for class
Object
- Instance fields for class
BaseClass
- Instance fields for class
DerivedClass
So in effect, if you ignore the DerivedClass
instance fields the object looks remarkably like an instance of BaseClass, and the JVM can reference the object as if it were an instance of BaseClass and have no difficulty doing so.
Similarly, in the Class object for DerivedClass
is a "virtual method table" with:
- Virtual method pointers for
Object
- Virtual method pointers for
BaseClass
- Virtual method pointers for
DerivedClass
The JVM makes virtual calls by indexing into this table to find a specific method, knowing that, say, hashValue
is method number 5 and printTheGroceryList
is method number 23. The number needed to call a method is determined when a class is loaded and cached in the method reference data in calling classes, so calling a method is: Get the number, go the the Class object pointed to by the instance header, index into the virtual method table, pull out the pointer, and branch to the method.
But when you look closely you will see, eg, that the pointer in the Object
group that points to the hashValue
method actually points to the one in BaseClass
(if BaseClass overrides hashValue
). So the JVM can treat the object as if it were an Object
, invoke hashValue
, and seamlessly get the method in BaseClass
(or DerivedClass
, if it also overrides the method).
(*) In practice the instance fields may be intermingled to a degree, since "aligning" fields from a superclass may leave gaps in the heap allocation that fields from a subclass can fill. This is simply a trick to minimize object size.
When you create a new instance and the class constructor is called, enough memory is being reserved in the heap for that instance's attributes to be stored. Those attributes comprise both:
- Attributes directly belonging to your class definition;
- Attributes belonging to all upper nodes in your class hierarchy tree.
Yes, the superclass constructor is called, but with the sole purpose to initialize attributes of the superclass. It never means a new object of the superclass will be created.
Check these links, they may help you to understand the process:
- http://www.javaworld.com/article/2076204/core-java/understanding-constructors.html
- http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
- http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
On the second link, documentation states: It is new
which creates the object. That is: It reserves memory for all the class references (Object attributes) and primitive values.
Then, the constructor is called, and its aim is to initialize enclosing class' attributes.
Since the object attributes are references in Java, the constructor may use new
to create object attributes, their references will be the values stored in your object's memory.
The superclass constructor just continues this task for your class inherited attributes.
An object is identified by its address, stored in variables of object types. the new
operator returns that address, and only one address, so there can only be one object. You can check this by looking at System.identityHashCode(this)
in sub- and superclass constructor, for example.
Base Class's object is not instantiated when a Derived Class's object is instantiated. Inheritance only brings certain attributes and methods of Base Class to Derived Class. Constructors/destructor of base class are called along with those of derived class when object of derived class is made/destroyed. But this does not mean object of base class is also made.