【发布时间】:2012-11-01 10:13:47
【问题描述】:
想象一下 MyOpenedFile 是用打开的流包装文件的东西。然后假设这段代码:
// method in an Util class
static void safeClose(MyOpenedFile f) {
if (f != null) {
try {
f.close();
} catch(IOException ex) { /* add logging or console output */ }
}
}
问题的实际方法:
void doSomeFileOperation(...) throws IOException, ... {
MyOpenedFile f1 = null;
MyOpenedFile f2 = null;
try {
/* method's "business logic" code beings */
f1 = new MyOpenedFile(...);
//do stuff
f2 = new MyOpenedFile(...);
// do stuff
f1.close(); f1 = null;
// do stuff with f1 closed
f2.close(); f2 = null;
// do stuff with f2 closed
/* method's "business logic" code ends */
} finally {
Util.safeClose(f1); f1 = null;
Util.safeClose(f2); f2 = null;
}
}
现在这很混乱,特别容易出错(例如,finally 块中的某些代码可能很难在单元测试中调用)。例如,在 C++ 中,析构函数会负责清理(由作用域指针析构函数调用或直接调用),代码会更干净。
那么,有没有更好/更好/更简洁的方法来包装上面的业务逻辑代码,以便传播任何异常但 f1 和 f2 两个文件都被关闭(或者至少在两者上都尝试关闭,即使失败)?
还有指向任何开源库(例如 Apache Commons)的答案,欢迎提供漂亮的包装器。
【问题讨论】:
-
顺便说一句,您的代码示例中有一个错误,实际上会导致您泄漏文件句柄,因为您在关闭它之前设置了 f1=null。
-
@Chii 不,据我所知,它没有。有
close或safeClose之前 所有null分配。 -
为什么每个文件都调用
close两次(在try和finally中)? -
@home 我没有。我只想要一个虚拟业务逻辑来描述一个关闭文件并将引用设置为 null 的案例。如果 finally 块中的引用为空,则不对其执行任何操作。
-
@hyde:啊,我看错了你的样本。这很有趣,因为它很容易误读使用这种带有内务管理的穿插逻辑风格编写的代码。但是,您不能重写它,因为要求 f1 关闭而 f2 保持打开状态(否则,您可以重写示例,使逻辑被传入,而内务管理则松散在别处
标签: java exception file-io raii resource-cleanup