假设,我有一个返回Result类实例的方法:
public class Result {
pubilc InputStream content;
public long contentLength;
}
我想使用此InputStream安全地工作,但是显然,由于Result不会影响Closeable,所以我不能只写这样的东西:
try (Result result = getResult()) {
...
}
一种可能的解决方案是使Result Closeable:
public class Result implements Closeable {
public InputStream content;
public long contentLength;
@Override
public void close() throws IOException {
content.close();
}
}
...
// this should work now
try (Result result = getResult()) {
...
} catch (IOException) {
...
}
但是,如果我无法(或不想)修改结果怎么办?
另一种方法是手动调用close(),但这有点笨重:
Result result = null;
try {
result = getResult();
...
} catch (...) {
...
} finally {
if (result != null) {
result.content.close();
}
}
我也考虑过这样的事情:
Result result = getResult();
try (InputStream stream = result.content) {
...
}
但是如果getResult()抛出异常,它将失败。
所以我的问题是:在这种情况下还有其他选择吗?
答案 0 :(得分:3)
您可以创建工厂方法来创建Autocloseable
包装器。
public Autocloseable autocloseable(Result result) {
return new Autocloseable() {
public void close() {
result.content.close();
}
}
}
然后使用像这样的try-with-resources
Result result = getResult();
try (Autocloseable ac = autocloseable(result)) {
doStuffWith(result);
}
或者,当然是过度设计
class AutoclosingWrapper<T> implements Autocloseable {
private T object;
private Function<T, Autocloseable> autocloseable;
public AutoclosingWrapper(Supplier<T> c, Function<T, Autocloseable> a) {
this(c.get(), a);
}
public AutoclosingWrapper(T t, Function<T, Autocloseable> a) {
object = t;
autocloseable = a;
}
public T getObject() {
return object;
}
public void close() {
autocloseable.apply(object).close();
}
}
被称为
try (AutoclosingWrapper<Result> wrapper = new AutoclosingWrapper(this::getResult, r -> r.content)) {
doStuffWith(wrapper.getObject());
}
答案 1 :(得分:2)
也许不是很好,但是很明显:
Result result = getResult();
try (InputStream content = result.content) {
...
}
可以变成
Result result;
try (InputStream content = (result = getResult()).content) {
...
}