作为一名java开发人员,我想了解IDisposable接口。有人可以尝试解释这个以及它与Java中发生的情况有何不同?感谢。
答案 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中所示)。
您还有机会使用非托管资源,您将负责内存分配及其发布。
当您不再需要资源时,可以调用此方法。