假设我的类有一个方法 start() 获取资源和 stop() 释放资源。类的 start 方法可以调用成员对象的 start() 方法。如果其中一个成员对象的 start() 引发异常,我必须确保为 start() 成功的所有成员对象调用 stop()。
class X {
public X ()
{
a = new A();
b = new B();
c = new C();
d = new D();
}
public void start () throws Exception
{
try {
a.start();
} catch (Exception e) {
throw e;
}
try {
b.start();
} catch (Exception e) {
a.stop();
throw e;
}
try {
c.start();
} catch (Exception e) {
b.stop();
a.stop();
throw e;
}
try {
d.start();
} catch (Exception e) {
c.stop();
b.stop();
a.stop();
throw e;
}
}
public void stop ()
{
d.stop();
c.stop();
b.stop();
a.stop();
}
private A a;
private B b;
private C c;
private D d;
}
注意清理代码的二次增长。进行清理的最佳方法是什么(最少的代码)?在 CI 中,可以通过函数底部的清理代码和“goto”轻松地做到这一点,以跳转到适当的位置,但是 Java 没有 goto。请注意,不允许在尚未启动 () 的对象上调用 stop() - 我正在寻找与上述完全相同但更短的代码。
到目前为止,我找到的唯一解决方案是使用布尔值来记住开始的内容,如下所示:
public void start () throws Exception
{
boolean aStarted = false;
boolean bStarted = false;
boolean cStarted = false;
boolean dStarted = false;
try {
a.start();
aStarted = true;
b.start();
bStarted = true;
c.start();
cStarted = true;
d.start();
dStarted = true;
} catch (Exception e) {
if (dStarted) d.stop();
if (cStarted) c.stop();
if (bStarted) b.stop();
if (aStarted) a.stop();
throw e;
}
}
我知道“finally”和“try-with-resources”,但这些似乎都不适用这里,因为如果没有例外,资源不应该被释放。
PS这不是关于我使用异常或我的程序设计的问题。这特别是关于在初始化代码失败的情况下进行清理。