Java中的IDisposable隐喻?

Java中的IDisposable隐喻?,java,.net,Java,.net,作为一名进入.NET的java开发人员,我想了解IDisposable接口。有人能解释一下这一点吗?它与Java中发生的事情有何不同?谢谢。我写了一封信 这里的基本思想是,有时您确实需要确定的资源处置。IDisposable提供了这种机制 例如,假设您在窗口中有一个控件。创建该句柄时,它会在内部创建一个windows句柄(HWND)。当您从窗口中删除该控件,并且不再使用它时,该控件将符合垃圾收集的条件,但不会立即被收集。事实上,我们无法保证需要多长时间才能收到 在GC运行并处理孤立控件之前,它仍

作为一名进入.NET的java开发人员,我想了解IDisposable接口。有人能解释一下这一点吗?它与Java中发生的事情有何不同?谢谢。

我写了一封信

这里的基本思想是,有时您确实需要确定的资源处置。IDisposable提供了这种机制

例如,假设您在窗口中有一个控件。创建该句柄时,它会在内部创建一个windows句柄(HWND)。当您从窗口中删除该控件,并且不再使用它时,该控件将符合垃圾收集的条件,但不会立即被收集。事实上,我们无法保证需要多长时间才能收到

在GC运行并处理孤立控件之前,它仍然会使用资源,因为它仍然持有HWND


IDisposable提供了一种方法,用于对象的用户显式清理包含需要与GC分离的代码的对象。在控件的情况下,我们可以调用
myControl.Dispose(),
,它将立即同步清理控件使用的“本机”资源(HWND)。

没有等效的

当您使用非托管资源(在Java中,所有资源区域都是托管的)时,会使用它

由托管资源分配的.net内存由GC自动收集(如在Java中)

此外,您还有机会使用非托管资源,您将负责内存分配及其释放


当不再需要资源时,可以调用此方法

在某些情况下,您需要可靠地处置您的类所拥有的资源。例如,应该在适当的时间关闭打开的连接,而不是在GC决定收集内存时。在.NET中,按惯例使用方法
Dispose
。可以在
try中调用它。。。最后
块,例如:

IConnection conn = OpenConnection();
try{
   ...
}finally{
    conn.Dispose();
}
因为这种模式被广泛使用,所以有一个语法糖:

using(IConnection conn = OpenConnection()){
} // Dispose is called at the end.
由于此语法非常简洁,因此有时在不拥有资源但需要在使用结束时执行某些操作的对象上实现
IDisposable
非常有用。例如考虑类< /P>
class TimeMeasure: IDisposable{
     public void Measure(string operation) { ... } // recourds operation time
     public void Dispose(){
        ... // print timings for all operations
     }
}
用法:

using(TimeMeasure m = new TimeMeasure())
{
    DoFoo();
    m.Measure("Foo");
    DoBar();
    m.Measure("Bar");
} // timings for 'Foo' and 'Bar' are printed here
在Java中,大致相当的接口是
可关闭的
。但是没有简单的语法来确保它的调用

应如何实现
IDisposable
?这有点棘手:

  • 如果您拥有资源,则需要确保它们可以通过显式
    Dispose
    调用或GC释放,但不能同时通过两者释放。所以,您需要一个标志来指示处置的事实。为了减少代码重复,将处置代码移动到单独的方法
例如:

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
    }
}
  • 如果您不持有资源,就像在
    TimeMeasure
    类中一样,不需要终结器,您只需在
    Dispose
    中执行必要的逻辑即可

基本上,IDisposable可以在较高的级别上使用,再加上
使用
关键字,可以为您看到的常见Java习惯用法提供语法支持,如下所示:

   Connection c = null;
   try {
      c = getConnection();
      ....
   } finally {
      if (c != null) {
          c.close();
      }
   }
   //psudo-Java
   using(Connection c = getConnection()) {
      .....
   }
如果Java有一个using关键字和一个带有
close()
方法的IDisposable接口,它可能会如下所示:

   Connection c = null;
   try {
      c = getConnection();
      ....
   } finally {
      if (c != null) {
          c.close();
      }
   }
   //psudo-Java
   using(Connection c = getConnection()) {
      .....
   }
在该块末尾隐式调用close方法。不需要尝试/最终


尽管如此,IDisposable有一个相当复杂的契约,主要涉及释放非托管内存。您必须努力使用Java才能拥有非托管内存(基本上是使用JNI和Swing组件,您有这个概念),但它在.NET中更为常见,因此对这个概念有语言支持。

在Java 1.7中引入了新的try with resource语句

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}
此处使用的对象必须实现自动关闭接口。它与IDisposable不完全相同,但在finally中自动调用
close()
。这为实现类似行为提供了机会

上面的代码与

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

请在中阅读更多关于此的信息。示例代码来自那里。

IDisposable接口用于手动释放非托管资源

快速问题-如何判断资源是否处于非托管状态,是否需要显式释放?查看它是否实现IDisposable.:)如果可以的话,通常都会处理IDisPobles。如果资源是非托管的,那么在实现该类时应该知道它。如果您不是在实现它,而是在使用它,那么就不需要特别注意。如果您需要决定显式处理,那么请尝试回答以下问题:“尽快释放资源是否比现在继续在此线程中执行更为关键?”。答案可能不同,例如web服务的一部分与GUI的一部分。@gil当您知道在程序中不再需要此引用时,您需要显式地进行处理。这绝对是可以接受的答案。不仅解释了一次性概念的工作原理,还展示了如何在Java上实现它。所有其他答案只涉及c#mechanism.AutoCloseable而非AutoCloseable