Java 中的 IDisposable 隐喻?

问题描述 投票:0回答:6

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

java .net
6个回答
20
投票

我写了一系列关于 IDisposable 的详细文章

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

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

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

IDisposable 为包含需要与 GC 分开清理的代码的对象提供了一种方法,以便由对象的用户显式清理。在控件的情况下,我们可以调用

myControl.Dispose(),
,它将立即同步清理控件使用的“本机”资源 (HWND)。


17
投票

java 1.7 中新引入了 try-with-resource 语句。

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

这里使用的对象必须实现AutoCloseable接口。它与 IDisposable 不完全相同,但

close()
在finally中自动调用。这提供了实现类似行为的机会。

上面的代码与

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

java 教程中阅读更多相关信息。示例代码来自那里。


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
    中执行必要的逻辑即可。

2
投票

基本上,高层的 IDisposable 与

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 中更常见,因此有对该概念的语言支持。


0
投票

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


-4
投票

没有同等的。

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

在 .net 中,由托管资源分配的内存由 GC 自动收集(与 Java 中一样)。

您还有机会使用非托管资源,您将负责内存分配和释放。

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

© www.soinside.com 2019 - 2024. All rights reserved.