IDisposable metaphor in Java?

后端 未结 6 1130
滥情空心
滥情空心 2021-02-19 13:44

As a java developer getting into .NET I\'d like to understand the IDisposable interface. Could somebody please try to explain this and how it differs from what happens in Java?

相关标签:
6条回答
  • 2021-02-19 13:58

    Basically IDisposable at a high level, combined with the using keyword is giving you syntactical support for what you see as a common Java idiom like this:

       Connection c = null;
       try {
          c = getConnection();
          ....
       } finally {
          if (c != null) {
              c.close();
          }
       }
    

    If Java had a using keyword and an IDisposable interface with a close() method, it might look like this:

       //psudo-Java
       using(Connection c = getConnection()) {
          .....
       }
    

    With the close method being implicitly called at the end of that block. No need for try/finally.

    That being said, IDisposible has a fairly complex contract, and is mainly concerned with freeing unmanaged memory. You have to work hard with Java to have unmanaged memory (basically with JNI and Swing components, you have the concept), but it is much more common in .NET, so there is language support for the concept.

    0 讨论(0)
  • 2021-02-19 14:11

    There're situations when you need reliable disposal for resources owned by your class. E.g., opened connection should be closed in proper time, not when GC decides to collect memory. In .NET method Dispose is used by convention for this. It can be called in try ... finally block, e.g.:

    IConnection conn = OpenConnection();
    try{
       ...
    }finally{
        conn.Dispose();
    }
    

    Because this pattern is so widely used, there's a syntactic sugar for this:

    using(IConnection conn = OpenConnection()){
    } // Dispose is called at the end.
    

    As this syntax is very concise, sometimes it's useful to implement IDisposable on objects that don't own resources, but need some operation be executed at the end of its usage. E.g. consider class

    class TimeMeasure: IDisposable{
         public void Measure(string operation) { ... } // recourds operation time
         public void Dispose(){
            ... // print timings for all operations
         }
    }
    

    Usage:

    using(TimeMeasure m = new TimeMeasure())
    {
        DoFoo();
        m.Measure("Foo");
        DoBar();
        m.Measure("Bar");
    } // timings for 'Foo' and 'Bar' are printed here
    

    In Java more or less equivalent interface is Closeable. But there's no simple syntax to ensure its calls.

    How IDisposable should be implemented? This is a bit tricky:

    • if you own resources, you need to ensure they can be freed by explicit Dispose call or by GC but not by both. So, you need a flag indicating fact of disposal. For less code duplication, the disposal code is moved to separate method.

    Example:

    bool disposed;
    public void Dispose(){
        Dispose(true);
        GC.SuppressFinalize(this); // tell GC not to call Finalizer() for this object
    }
    
    ~MyObject(){
        Dispose(false);
    }
    
    void Dispose(bool manualDisposing){
        if(!disposed){
            disposed = true;
            if(manualDisposing)
               ... // call Dispose on all IDisposable fields
            ... // dispose all native resources
        }
    }
    
    • if you are not holding resources, as in case of TimeMeasure class, no need for Finalizer, you just do necessary logic in Dispose.
    0 讨论(0)
  • 2021-02-19 14:15

    There is no equivalent.

    It is used when you use unmanaged resources ( in Java all the resources area managed ).

    In .net memory allocated by the managed resources is collected automatically by the GC ( as in Java ) .

    You have additionally the opportunity to use unmanaged resources, where you will be responsible for the memory allocation and its release.

    You call this method when you don't need the resources anymore.

    0 讨论(0)
  • 2021-02-19 14:21

    With java 1.7 there is the new introduced try-with-resource statement.

    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
    

    The objects used here must implement AutoCloseable interface. It is not exactly the same as IDisposable, but the close() is called automatically in the finally. This gives the oportunity to implement similar behavior.

    The code above is the same as

    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
    

    Read more about this in java tutorial. The samplecode is coming from there.

    0 讨论(0)
  • 2021-02-19 14:22

    IDisposable interface is used to free the unmanaged resources manually.

    0 讨论(0)
  • 2021-02-19 14:24

    I wrote a detailed series of articles on IDisposable.

    The basic idea here is that sometimes you DO need deterministic disposal of resources. IDisposable provides that mechanism.

    For example, say you have a control in a Window. When this is created, it creates a windows handle (HWND) internally. When you remove the control from the Window, and its no longer used, the control becomes eligible for garbage collection - but it does not get collected right away. In fact, there are no guarantees as to how long it will be before it is collected.

    Until the GC runs and processes the orphaned control, it will still use resources, since it's still holding the HWND.

    IDisposable provides a means for objects that contain code that needs cleanup separate from the GC to be explicitly cleaned up by the user of the object. In the control's case, we can call myControl.Dispose(), which will immediately, synchronously cleanup the "native" resources (HWND) used by the control.

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