Why the output of the following program runs finalize of Classmate before finalize() of Course ? Classmate uses the class Course object so its finalize() should run after the finalize() of Course ? But the output shows the reverse.WHY?
class Classmate{
Course mca;
Classmate(){
System.out.println("Student const. `enter code here`called");
mca = new Course();
mca.getCourse();
}
@Override
protected void finalize() {System.out.println("good bye Student");
}
}
class Course{
Course(){
System.out.println("Course const. called");
}
void getCourse(){
System.out.println("your ccourse is MCA");
}
@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
System.out.println("goodbye course");
}
}
public class Composition {
public static void main(String[] args) {
Classmate ram = new Classmate();
ram=null;
System.gc();
for(int i=0;i<5;i++)
System.out.println("i is "+i);
}
}
OUTPUT:
Student const. called
Course const. called
your ccourse is MCA
good bye Student
i is 0
goodbye course
i is 1
i is 2
i is 3
i is 4
It does so to teach you (and any other Java programmer) a lesson. That lesson is: don't make assumptions about when (or better if) finalize is called.
Seriously: you can check out this great question and will find that calls to finalize are bound to the actions of the garbage collector. And thing is: you absolutely have no control or "insight" when the garbage collector decides to collect stuff. Most of the time, its activities will lead to identical results ... if you don't make changes to the "setup" you are dealing with. Like: running the very same example using the very same JVM settings. But as soon as you start looking at "real world" applications ... you will encounter unexpected surprises all the time.
Heck - it is not even guaranteed that finalize is ever called. So, your code should not rely on it. So, there are close to zero good reasons to use finalize at all.
In other words: if you really want to understand what is going on; you would have to dive into the implementation of the GC your JVM is using; to understand why and when that GC is defining garbage; and when it starts collecting that garbage.