繁体   English   中英

如何在Java中组合Closeable对象?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM