Is there a destructor for Java?

前端 未结 22 1383
[愿得一人]
[愿得一人] 2020-11-22 11:47

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 m

相关标签:
22条回答
  • 2020-11-22 12:24

    Because Java is a garbage collected language you cannot predict when (or even if) an object will be destroyed. Hence there is no direct equivalent of a destructor.

    There is an inherited method called finalize, but this is called entirely at the discretion of the garbage collector. So for classes that need to explicitly tidy up, the convention is to define a close method and use finalize only for sanity checking (i.e. if close has not been called do it now and log an error).

    There was a question that spawned in-depth discussion of finalize recently, so that should provide more depth if required...

    0 讨论(0)
  • 2020-11-22 12:24

    I fully agree to other answers, saying not to rely on the execution of finalize.

    In addition to try-catch-finally blocks, you may use Runtime#addShutdownHook (introduced in Java 1.3) to perform final cleanups in your program.

    That isn't the same as destructors are, but one may implement a shutdown hook having listener objects registered on which cleanup methods (close persistent database connections, remove file locks, and so on) can be invoked - things that would normally be done in destructors. Again - this is not a replacement for destructors but in some cases, you can approach the wanted functionality with this.

    The advantage of this is having deconstruction behavior loosely coupled from the rest of your program.

    0 讨论(0)
  • 2020-11-22 12:24

    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 a close method) you could put them in a Bag 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 the Closeables closing them... ?

    The code would probably look something like this:

    accessor.getPlaypen().closeCloseables();
    accessor.setPlaypen( new Playpen() );
    

    closeCloseables would probably be a blocking method, probably involving a latch (e.g. CountdownLatch), to deal with (and wait as appropriate for) any Runnables/Callables in any threads specific to the Playpen to be ended as appropriate, in particular in the JavaFX thread.

    0 讨论(0)
  • 2020-11-22 12:24

    I used to mainly deal with C++ and that is what lead me to the search of a destructor as well. I am using JAVA a lot now. What I did, and it may not be the best case for everyone, but I implemented my own destructor by reseting all the values to either 0 or there default through a function.

    Example:

    public myDestructor() {
    
    variableA = 0; //INT
    variableB = 0.0; //DOUBLE & FLOAT
    variableC = "NO NAME ENTERED"; //TEXT & STRING
    variableD = false; //BOOL
    
    }
    

    Ideally this won't work for all situations, but where there are global variables it will work as long as you don't have a ton of them.

    I know I am not the best Java programmer, but it seems to be working for me.

    0 讨论(0)
  • 2020-11-22 12:25

    Use of finalize() methods should be avoided. They are not a reliable mechanism for resource clean up and it is possible to cause problems in the garbage collector by abusing them.

    If you require a deallocation call in your object, say to release resources, use an explicit method call. This convention can be seen in existing APIs (e.g. Closeable, Graphics.dispose(), Widget.dispose()) and is usually called via try/finally.

    Resource r = new Resource();
    try {
        //work
    } finally {
        r.dispose();
    }
    

    Attempts to use a disposed object should throw a runtime exception (see IllegalStateException).


    EDIT:

    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?

    Generally, all you need to do is dereference the objects - at least, this is the way it is supposed to work. If you are worried about garbage collection, check out Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning (or the equivalent document for your JVM version).

    0 讨论(0)
  • 2020-11-22 12:26

    Many great answers here, but there is some additional information about why you should avoid using finalize().

    If the JVM exits due to System.exit() or Runtime.getRuntime().exit(), finalizers will not be run by default. From Javadoc for Runtime.exit():

    The virtual machine's shutdown sequence consists of two phases. In the first phase all registered shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish. In the second phase all uninvoked finalizers are run if finalization-on-exit has been enabled. Once this is done the virtual machine halts.

    You can call System.runFinalization() but it only makes "a best effort to complete all outstanding finalizations" – not a guarantee.

    There is a System.runFinalizersOnExit() method, but don't use it – it's unsafe, deprecated long ago.

    0 讨论(0)
提交回复
热议问题