Is there a destructor for Java? I don't seem to be able to find any documentation on this. If there isn't, how can I achieve the same effect?
To make my question more specific, I am writing an application that deals with data and the specification say that there should be a 'reset' button that brings the application back to its original just launched state. However, all data have to be 'live' unless the application is closed or reset button is pressed.
Being usually a C/C++ programmer, I thought this would be trivial to implement. (And hence I planned to implement it last.) I structured my program such that all the 'reset-able' objects would be in the same class so that I can just destroy all 'live' objects when a reset button is pressed.
I was thinking if all I did was just to dereference the data and wait for the garbage collector to collect them, wouldn't there be a memory leak if my user repeatedly entered data and pressed the reset button? I was also thinking since Java is quite mature as a language, there should be a way to prevent this from happening or gracefully tackle this.
No,
java.lang.Object#finalize
is the closest you can get.However, when (and if) it is called, is not guaranteed.
See:
java.lang.Runtime#runFinalizersOnExit(boolean)
There is a @Cleanup annotation in Lombok that mostly resembles C++ destructors:
When processing it (at compilation time), Lombok inserts appropriate
try-finally
block so thatresource.close()
is invoked, when execution leaves the scope of the variable. You can also specify explicitly another method for releasing the resource, e.g.resource.dispose()
:If it's just memory you are worried about, don't. Just trust the GC it does a decent job. I actually saw something about it being so efficient that it could be better for performance to create heaps of tiny objects than to utilize large arrays in some instances.
Just thinking about the original question... which, I think we can conclude from all the other learned answers, and also from Bloch's essential Effective Java, item 7, "Avoid finalizers", seeks the solution to a legitimate question in a manner which is inappropriate to the Java language...:
... wouldn't a pretty obvious solution to do what the OP actually wants be to keep all your objects which need to be reset in a sort of "playpen", to which all other non-resettable objects have references only through some sort of accessor object...
And then when you need to "reset" you disconnect the existing playpen and make a new one: all the web of objects in the playpen is cast adrift, never to return, and one day to be collected by the GC.
If any of these objects are
Closeable
(or not, but have aclose
method) you could put them in aBag
in the playpen as they are created (and possibly opened), and the last act of the accessor before cutting off the playpen would be to go through all theCloseables
closing them... ?The code would probably look something like this:
closeCloseables
would probably be a blocking method, probably involving a latch (e.g.CountdownLatch
), to deal with (and wait as appropriate for) anyRunnables
/Callables
in any threads specific to thePlaypen
to be ended as appropriate, in particular in the JavaFX thread.With Java 1.7 released, you now have the additional option of using the
try-with-resources
block. For example,If you execute this class,
c.close()
will be executed when thetry
block is left, and before thecatch
andfinally
blocks are executed. Unlike in the case of thefinalize()
method,close()
is guaranteed to be executed. However, there is no need of executing it explicitly in thefinally
clause.First, note that since Java is garbage-collected, it is rare to need to do anything about object destruction. Firstly because you don't usually have any managed resources to free, and secondly because you can't predict when or if it will happen, so it's inappropriate for things that you need to occur "as soon as nobody is using my object any more".
You can be notified after an object has been destroyed using java.lang.ref.PhantomReference (actually, saying it has been destroyed may be slightly inaccurate, but if a phantom reference to it is queued then it's no longer recoverable, which usually amounts to the same thing). A common use is:
There is also finalize(), which looks like a destructor but doesn't behave like one. It's usually not a good option.