英文:
Move resource out of try-with
问题
我想创建一个包装资源的类实例。问题是:当构造函数抛出异常时,资源会丢失。我正在尝试找到解决方案。"Try-with-resource" 是一个看起来适合这种情况的结构,但我不能将资源从中移出。
例如,一个包装 HTTP 客户端的服务客户端:
class ServiceClient implements Closeable {
ServiceClient(ClosableHTTPClient client) { /* ... */ }
public void close() { client.close(); }
public ServiceClient create(String url) throws IOException {
try (ClosableHTTPClient client = createHttpClient(url)) {
return new ServiceClient(client);
} // 使 try-with 不在成功时关闭 `client`
}
public ClosableHTTPClient createHttpClient(String url) {
return HttpClientBuilder.create()
.setConnectionManager(createClosableConnectionManager()) // 在 `build` 抛出异常时必须关闭
.build();
}
}
英文:
I want to create a class instance which wraps a resource. The problem: when the constructor throws, the resource is lost. I'm trying to find a solution for that. Try-with-resource is a construct that seems good for that, but I can not move the resource out of it.
For example, a service client that wraps a HTTP client:
class ServiceClient implements Closeable {
ServiceClient(ClosableHTTPClient client) { /* ... */ }
public close() { client.close() }
public ServiceClient create(String url) throws IOException {
try (ClosableHTTPClient client = createHttpClient(url)) {
return new ServiceClient(client);
} // make try-with do not close `client` on success
}
public ClosableHTTPClient createHttpClient(String url) {
return HttpClientBuilder.create()
.setConnectionManager(createClosableConnectionManager()) // must be closed, when `build` throws
.build();
}
}
答案1
得分: 0
构造函数抛出异常。
class Foo implements AutoClosable {
private final Bar someResource;
/**
* @param someResource 要接管所有权的资源。
*/
Foo(Bar someResource) {
this.someResource = someResource;
try {
...
} catch (Throwable e) {
someResource.close(); // 如果 this.close 不是 final 的。
throw e;
}
}
@Override public void close() { someResource.close(); }
...
}
唯一的解决方案是处理构造函数中抛出的任何异常。
甚至连标准的 Java 类有时也会忽略(具有负容量的 BufferedReader 将不会关闭其包装的 reader)。
英文:
A constructor throwing an exception.
class Foo implements AutoClosable {
private final Bar someResource;
/**
* @param someResource whose ownership is taken over.
*/
Foo(Bar someResource) {
this.someResource = someResource;
try {
...
} catch (Throwable e) {
someResource.close(); // If this.close is not final.
throw e;
}
}
@Override public void close() { someResource.close(); }
...
The only solution is taking care of any exception thrown in the constructor.
Event the standard java classes sometimes forget (a BufferedReader with negative capacity will not close its wrapped reader).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论