Java中的IDisposable隐喻?

时间:2009-11-20 03:12:55

标签: java .net

作为一名java开发人员,我想了解IDisposable接口。有人可以尝试解释这个以及它与Java中发生的情况有何不同?感谢。

6 个答案:

答案 0 :(得分:18)

我写了detailed series of articles on IDisposable

这里的基本思想是,有时你需要确定性地处理资源。 IDisposable提供了这种机制。

例如,假设您在Window中有一个控件。创建它时,它会在内部创建一个Windows句柄(HWND)。当您从Window中删除控件并且不再使用它时,该控件将有资格进行垃圾回收 - 但它不会立即收集。事实上,无法保证在收集之前需要多长时间。

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

IDisposable为包含代码的对象提供了一种方法,这些代码需要与GC分开进行清理才能被对象的用户明确清理。在控件的情况下,我们可以调用myControl.Dispose(),,它将立即同步清除控件使用的“本机”资源(HWND)。

答案 1 :(得分:12)

使用java 1.7,新引入了try-with-resource语句。

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

此处使用的对象必须实现AutoCloseable接口。它与IDisposable不完全相同,但在finally中自动调用close()。这使得机会能够实现类似的行为。

上面的代码与

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

java tutorial了解详情。样本代码来自那里。

答案 2 :(得分:7)

在某些情况下,您需要对您所拥有的资源进行可靠的处理。例如,打开的连接应在适当的时间关闭,而不是在GC决定收集内存时。在.NET中,方法Dispose用于此。它可以在try ... finally块中调用,例如:

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

因为这种模式被广泛使用,所以有一个语法糖:

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

由于此语法非常简洁,有时在不拥有资源的对象上实现IDisposable很有用,但需要在其使用结束时执行某些操作。例如。考虑上课

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中,或多或少等效的接口是Closeable。但是没有简单的语法来确保其调用。

应该如何实施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课程,则不需要Finalizer,您只需在Dispose中执行必要的逻辑。

答案 3 :(得分:2)

基本上IDisisposable在高级别上与using关键字相结合,为您提供语法支持,你会看到像这样的常见Java习语:

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

如果Java有一个using关键字和一个带有close()方法的IDisposable接口,它可能如下所示:

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

在该块的末尾隐式调用close方法。无需尝试/终于。

话虽如此,IDisposible有一个相当复杂的合同,主要涉及释放非托管内存。你必须努力使用Java才能拥有非托管内存(基本上使用JNI和Swing组件,你有这个概念),但它在.NET中更常见,所以对这个概念有语言支持。

答案 4 :(得分:0)

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

答案 5 :(得分:-3)

没有等价物。

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

由受管资源分配的.net内存由GC自动收集(如Java中所示)。

您还有机会使用非托管资源,您将负责内存分配及其发布。

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