Paul said:
I.e., a destructor... that you have to remember to call
manually.
Which is not really that different from C++. C++ destructors are invoked
manually as well by calling delete.
I like to explain the difference between C++ and Java this way. There
are basically 3 parts of the end of the lifecycle of an object:
1. Releasing of non-memory resources
2. Freeing of the object's memory
3. Elimination of the last reference to an object.
The C++ model says that 1 & 2 occur at the same time when explicitly
commanded by the program through a delete statment. Number 3 may occur
sometime later, but will never occur before 1 & 2. This of course leads
to dangling pointers.
Java says that 2 will never occur before 3. There can never be a
dangling pointer. It places no restriction on when 1 occurs. The correct
way to do it is to have an explicit function that does #1. But through
the finalize method you can also do it when #2 occurs if you haven't
done it already.
Now one other difference between the 2 is that C++ allows objects to be
on the stack which will cause number 2 to occur without an explicit
delete call when the object goes out of scope. Of course, 2 can still
occur before 3. This can be used to free resources somewhat
automatically in C++ using an auto_ptr. Java puts all objects on the
heap, so objects never have a scope. The way to make sure something gets
cleaned up at the end of a scope in Java is to use a try-finally block.
It is a little more manual, but since Java only needs to do this for
non-memory resources it is not that common and generally only needs to
occur for files, DB connections, etc. In C++ you have to make sure that
memory resources are cleaned up yourself so you have to be more diligent
in using auto_ptr or explicit delete calls.
So from the perspective of the user of a class there is little difference:
- In C++ you do a delete to make sure that the resource is freed, in
Java you call a method on the object.
- You can still have a reference to the object afterward. In Java that
object will still exist so any attempts to use the object can be handled
safely. In C++ you are using a dangling pointer and can crash or destroy
data.
- C++ has an auto_ptr that can be used in some situations to free the
resources implicitly. Java has finally blocks that can be used to be
sure that the clean-up method is called explicitly. The finally block
only needs to be used when non-memory resources are concerned. In C++
you have to use the auto_ptr or some other mechanism for all resources
including memory. Also the C++ auto_ptr does not solve all problems. For
instance it doesn't work for multiple references to the same resource.
- In C++ if you don't explictly or implicitly free the resources they
will not be freed. With Java you have a safety net in the garbage
collector and the finalize method which can be used to free resources if
they haven't already been freed. It is not guaranteed to ever occur, but
some safety net is better than no safety net.