saima kanwal wrote:If Numbers extends BaseClass , so when new is called on Numbers, at line 9, then 3 objects must be created (instead of two): BaseClass (as Baseclass constructor is invoked being the super class of Numbers),Numbers , and the int array in the Baseclass. so when n is set to null ( at line 11), the same 3 objects must die .
BaseClass is not an 'Object', it is a 'Class'. Class is created/loaded by the class loader
on the first use of the class, and then lives on the heap until program dies (strictly speaking until class loader that holds reference to this class is unloaded
and garbage collected) ... but there are rather advanced topics and this is not covered by
SCJP objectives.
On SCJP they
test your knowledge only about 'Objects' creation and destroying.
Javaspec defines the object as:
An object is a class instance or an array. -
http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1
So - in the context of SCJP questions related to garbage collection - do not count 'classes' as 'objects', because this gives you wrong answers.
There are only 2 objects created:
- instance of class
Numbers (created by new Numbers)
- instance of field
int [] numbers created during object initialization.
saima kanwal wrote:Basically, I am confused about the number of objects created when there is a superclass and a subclass; should we consider the superclass as a separate object created when the subclass is instantiated?
You must know class instance initialization sequence.
Class instance initialization order is as follows:
1. if the class has an ancestor class (extends from base class) - first initialize the ancestor (base) class
(if base class has it's own ancestor - then the ancestor is initialized first ... and so on, and so on).
2. Initialize all field declarations (in the order they are declared in the class declaration).
3. Call all initialization blocks (in the order they are declared in the class declaration).
4. Call the class' constructor.
Look at this example:
The code above creates 12 objects on the heap.
- in line 39 we instatiate object of class C with new C()
- C extends from B - so first initialize B
- B extends from A - so first initialize A
- A extends from Object (class Object is the ancestor of all
java classes) - then first initialize Object
- in A - initialize all fields (if there is no explicit initializer declaration, assign null to the field)
- a1 = null
- a2 = new Integer(2) .... object 1 created !
- a3 = null
- in A - call all initialization blocks - there s only one initialization block in line 9, and in this block object no 2 is created and reference to this object is assigned to the a3 field
- in A - call constructor: in the constructor object no 3 is created, reference is assigned to a3
- A is initialized - continue initialization of B:
- in B: initialize all fields ..... b3 = new Integer()
- in B: call all initialization blocks ..... b1 = new Integer()
- in B: call constructor ..... b2 = new Integer(1)
- B is initialized - continue initialization of C
- in C: initialize all fields ... c1 = new Integer(1)
- in C: call all initialization blocks ... c3 = c2
- in C: call constructor: c2 = new Integer[]{2, 4, 6} ... here 4 objects are created!!! array itself, then 3 objects of Integer !!!
- C is initialized - return to the main block
- main: store reference of the new object C into the obj variable.
But ... there is only ONE object - instance of class C (despite of the fact that there are 4 classes involved: C extends from B, B extends from A and A extends from Object)
There are 2 tricks in this example you must be familiar with ... because you could met them on the exam.
First the declaration:
int [] num = new int[]{1,2,3} creates only ONE object on the heap (one array object)
but
Integer [] num = new Integer[]{1,2,3} creates FOUR objects - an array object plus 3 Integer instances (1,2,3 primitives are automatically autoboxed into Integer)
Second is related to the knowledge of the order of the object instance initialization order:
in line 28 value (reference) from c2 is stored to c3, however after line 46 the object referenced by c2 is eligible for GC;
the pitfall is that line 28 is executed before constructor in line 33, therefore c3 = null.
saima kanwal wrote:
Also, one more thing to be cleared: Here in this code , i feel that there is no use of line 12, because the object n is set to null at line 11 , and num[1] points to the same object, so it is already set to null. so i think num[1] = null (line 12)is not sending any objects to GC. am i correct or not??
n and num[1] are only
references to the object ... there are something like pointers in C/C++ or address to the memory space where the object
is allocated (in fact the reference is not the 'true' address, but an index to the JVM internal table that stores memory addresses and other internal informations about objects).
So if you store null in reference variable 'n', this does not change value of of other variables that hold the same reference
... when you assign null to 'n', num[1] still holds reference to the object.
I hope this helps