[英]How to compose Closeable objects in Java?
我正在尝试创建一个管理多个可Closeable
资源的Java类。 C ++解决方案可以直接使用大量资源轻松扩展:
class composed_resource
{
resource_a a;
resource_b b;
resource_c c;
composed_resource(int x)
: a(x), b(x), c(x)
{ }
~composed_resource()
{ }
};
我天真的Java解决方案:
public class ComposedResource implements Closeable
{
private final ResourceA a;
private final ResourceB b;
private final ResourceC c;
public ComposedResource(int x) /* throws ... */ {
a = new ResourceA(x);
try {
b = new ResourceB(x);
try {
c = new ResourceC(x);
} catch (Throwable t) {
b.close();
throw t;
}
} catch (Throwable t) {
a.close();
throw t;
}
}
@Override
public void close() throws IOException {
try {
a.close();
} finally {
try {
b.close();
} finally {
c.close();
}
}
}
}
略有改进的版本:
public class ComposedResource2 implements Closeable
{
private final ResourceA a;
private final ResourceB b;
private final ResourceC c;
public ComposedResource2(int x) /* throws ... */ {
try {
a = new ResourceA(x);
b = new ResourceB(x);
c = new ResourceC(x);
} catch (Throwable t) {
close();
throw t;
}
}
@Override
public void close() throws IOException {
try {
if (a != null) a.close();
} finally {
try {
if (b != null) b.close();
} finally {
if (c != null) c.close();
}
}
}
}
是否有更优雅的解决方案,避免嵌套的try-catch-blocks,同时仍保持异常安全? 它可以通过三种资源进行管理,但更多的是变得笨拙。 (如果它是本地范围,我可以使用“try-with-resources”语句,但这不适用于此。)
在使用java.rmi
时我想到了这一点。 在构造函数中,我正在创建/查找注册表,查找对象和导出对象。 close()需要取消注册和取消导出对象。 我想创建包装器对象来处理导出/取消导出(就像我在C ++中用来利用RAII),但后来我注意到这对我没什么帮助(我不是那么多Java专家,但我必须用它来上大学)。
目前我正在使用上面的ComposedResource2
东西,它运行正常。 但现在我有兴趣知道是否有更优雅的解决方案。
像这样使用try-with-resouces。
@Override
public void close() throws IOException {
try (Closeable cc = c;
Closeable bb = b;
Closeable aa = a;) {
// do nothing
}
}
怎么用这种方式更改close()?
@Override
public void close() {
close(a);
close(b);
close(c);
}
public void close(Closeable closeable) throws IOException{
if (closeable != null){
closeable.close();
}
}
我认为它更干净......
您还可以将3个资源作为“Closeables”进行管理,并将它们放在一个数组中,以便ComposedResource拥有您想要的尽可能多的资源。 做这样的事情:
public class ComposedResource{
List<Closeable> resources = new ArrayList<Closeable>();
public void add(Closeable c){
resources.add(c);
}
@Override
public void close(){
for (Closeable r : resources){
close(r);
}
}
public void close(Closeable c){
try{
c.close();
catch (IOException e){
log(e);
}
}
}
所以你将添加资源:
ComposedResource c = new ComposedResource();
c.add(new Resource1());
c.add(new Resource2());
c.add(new Resource3());
...
// do nice thinks
// and, to close;
c.close();
编辑:
@Mohit Kanwar建议以这种方式抛出异常:
@Override
public void close() throws IOException {
for (Closeable r : resources){
r.close(r);
}
}
并编辑了我的代码,@ Lii说,做这个例外将阻止关闭所有资源,我同意Lii所以我拒绝了Mohit的编辑...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.