Java中的IDisposable隐喻?

gil*_*gil 13 .net java

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

Ree*_*sey 18

在IDisposable上写了一系列详细的文章.

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

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

在GC运行并处理孤立控制之前,它仍将使用资源,因为它仍然保持HWND.

IDisposable为包含需要与GC分离的清理的代码提供了一种方法,以便由对象的用户明确清理.在控件的情况下,我们可以调用myControl.Dispose(),哪个将立即同步清理控件使用的"本机"资源(HWND).

  • 看看它是否实现了IDisposable.:)如果可以的话,几乎总是处理你的IDisposables. (3认同)
  • 快速提问 - 如何判断资源是否未受管理且需要明确处理? (2认同)

Chr*_*467 13

在java 1.7中,引入了新的try-with-resource语句.

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}
Run Code Online (Sandbox Code Playgroud)

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

上面的代码与

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

java教程中阅读更多相关内容.样本代码来自那里.

  • 这绝对应该是公认的答案。不仅解释了一次性概念的工作原理,还展示了它是如何在 Java 上实现的。所有其他答案仅参考 c# 机制。 (3认同)

eld*_*rge 7

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

IConnection conn = OpenConnection();
try{
   ...
}finally{
    conn.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

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

using(IConnection conn = OpenConnection()){
} // Dispose is called at the end.
Run Code Online (Sandbox Code Playgroud)

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

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

用法:

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

在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
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 如果你没有持有资源,就像TimeMeasure上课一样,不需要Finalizer,你只需要做必要的逻辑Dispose.