1.尝试资源
try (
A a = new A();
B b = new B();
C c = new C()
) {
// ...
}
除了好又短,它也是正确的.
>它将正确关闭a,b和c中的任何一个需要关闭.
>此外,它还将“抑制”在关闭期间发生的异常,如果从正文抛出异常(这是对try / finally的改进,可以在这里阅读https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)
2.番石榴更接近
对于JDK7之前的版本,有一个Guava的Closer,用途如下:
Closer closer = Closer.create();
try {
A a = closer.register(new A());
B b = closer.register(new B());
C c = closer.register(new C());
// ...
} catch (Throwable e) { // must catch Throwable
throw closer.rethrow(e);
} finally {
closer.close();
}
虽然稍微长一点,但它的效果还不错(请点击这里https://github.com/google/guava/wiki/ClosingResourcesExplained#closer以获取更多信息)
拥有多个资源的对象怎么样?
说我有:
public class P implements AutoCloseable {
private A a;
private B b;
private C c;
public P() {
a = new A();
b = new B();
c = new C();
}
public close() {
c.close();
b.close();
a.close();
}
}
此代码存在多个问题:
>如果从构造函数抛出异常,则不会关闭任何内容(调用者没有要调用的实例关闭)
>如果从关闭引发异常,则不会关闭某些资源
1和2都没有遇到这些问题.然而:
>尝试资源显然不能使用,因为P的生命周期由调用者控制
> Guava Closer似乎也无法使用.虽然它更灵活,但它不支持close-and-rethrow,这是构造函数所必需的
最佳答案
您可以使用execute around方法模式从资源包装类的用户隐藏资源的打开和关闭.这样您就可以确保始终关闭资源.您应该为不同的用例添加单独的操作方法.只有当这是一个公共资源并且被应用程序的许多部分使用时,这才有用.
这是一个例子
public class ResourceWrapper {
private A a;
private B b;
private C c;
private ResourceWrapper() {
// add try catch if you have to,after cleanup then throw exception if ithappens
a = new A();
b = new B();
c = new C();
}
/**
* add required operation methods
*/
public ResourceWrapper op1() {
// do some operations
return this;
}
public ResourceWrapper op2() {
// if additional add or different
return this;
}
// close everything here
private void close() {
// check null if you have to
// add try catch if you have to
c.close();
b.close();
a.close();
}
public static void use(Consumeropening and closing the resource wrapped around the operation methods by the owner of the Resource.
*
*/
public static void main(String[] args) {
ResourceWrapper.use(resource->resource.op1().op2());
}
}