Statement #1: Dozens[] da=new Dozens[3];//object 2 Will create a reference name "da" in the main method stack and a new Array object in the Heap which can hold three objects of type Dozens.
Hence this statement will have one object of type Array on the heap which is refered by da.
Statement #2: da[0]=new Dozens();//object 3 : Will create a new Dozens object in heap and assigned to da[0]. Before the Dozens() constructor runs the member variable of Dozens dz will result in a new Array object creation. Hence after this statement completes there will be two more objects in the heap , first of type Dozens assigned to da[0] and a new array object assigned to dz memeber variable of da[0]. Hence every new Dozens object will result in two new object on heap.
Hence there are a total of 3 objects in the heap.
Statement# 3: Dozens d=new Dozens();//object 4 Will result in two more objects as explained above.
Hence there are a total of 5 objects in the heap.
da[1]=d; Will cause the second element of da array to refer the above object created by d.
Still there are a total of 5 objects in the heap.
d=null; Will cause the reference d to point to null but the object which it pointer earlier can still be refered from da[1] . Hence Still there are a total of 5 objects in the heap.
Still none of the objects are eligible for garbage collection.
da[1]=null; Will cause the object created by statement #3 no longer accessible from any live
thread and hence that object will be available for GC. Since its a Dozens object it will cause dz also to be available for GC because although dz can be accessed via its object but the object itself cannot be accessed from live thread.
Hence a total of 5 objects are created and 2 objects are eligible for GC.
Note "da" & "d" are local variables in the main method stack and not objects in HEAP.