当资源位于不可关闭的包装器内时,Java尝试使用资源
假设有一个方法返回结果类的实例:当资源位于不可关闭的包装器内时,Java尝试使用资源,java,try-with-resources,Java,Try With Resources,假设有一个方法返回结果类的实例: public class Result { pubilc InputStream content; public long contentLength; } 我想安全地使用这个InputStream,但很明显,由于结果不可关闭,我不能这样写: try (Result result = getResult()) { ... } Result result = getResult(); try (InputStream stream =
public class Result {
pubilc InputStream content;
public long contentLength;
}
我想安全地使用这个InputStream,但很明显,由于结果不可关闭,我不能这样写:
try (Result result = getResult()) {
...
}
Result result = getResult();
try (InputStream stream = result.content) {
...
}
可能的解决方案之一是使结果接近:
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();
}
}
我也想到了这样的事情:
try (Result result = getResult()) {
...
}
Result result = getResult();
try (InputStream stream = result.content) {
...
}
但如果getResult()引发异常,则它将失败
所以我的问题是:在这种情况下还有其他选择吗?您可以创建一个工厂方法来创建一个可自动关闭的包装器
public Autocloseable autocloseable(Result result) {
return new Autocloseable() {
public void close() {
result.content.close();
}
}
}
然后使用像这样的资源进行尝试
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();
}
}
类AutoclosingWrapper实现自动关闭{
私人T对象;
专用功能自动关闭;
公共自动关闭包装器(供应商c,功能a){
这(c.get(),a);
}
公共自动关闭包装器(T,函数a){
对象=t;
自动关闭=a;
}
公共T getObject(){
返回对象;
}
公众假期结束(){
自动关闭。应用(对象)。关闭();
}
}
这叫做
try (AutoclosingWrapper<Result> wrapper = new AutoclosingWrapper(this::getResult, r -> r.content)) {
doStuffWith(wrapper.getObject());
}
try(AutoclosingWrapper=newautoclosingwrapper(this::getResult,r->r.content)){
doStuffWith(wrapper.getObject());
}
您可以创建一个工厂方法来创建一个可自动关闭的包装器
public Autocloseable autocloseable(Result result) {
return new Autocloseable() {
public void close() {
result.content.close();
}
}
}
然后使用像这样的资源进行尝试
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();
}
}
类AutoclosingWrapper实现自动关闭{
私人T对象;
专用功能自动关闭;
公共自动关闭包装器(供应商c,功能a){
这(c.get(),a);
}
公共自动关闭包装器(T,函数a){
对象=t;
自动关闭=a;
}
公共T getObject(){
返回对象;
}
公众假期结束(){
自动关闭。应用(对象)。关闭();
}
}
这叫做
try (AutoclosingWrapper<Result> wrapper = new AutoclosingWrapper(this::getResult, r -> r.content)) {
doStuffWith(wrapper.getObject());
}
try(AutoclosingWrapper=newautoclosingwrapper(this::getResult,r->r.content)){
doStuffWith(wrapper.getObject());
}
也许不太好,但很明显:
Result result = getResult();
try (InputStream content = result.content) {
...
}
可以变成
Result result;
try (InputStream content = (result = getResult()).content) {
...
}
也许不太好,但很明显:
Result result = getResult();
try (InputStream content = result.content) {
...
}
可以变成
Result result;
try (InputStream content = (result = getResult()).content) {
...
}
但如果我不能修改结果(或不想修改),该怎么办?然后,您将无法使其自动关闭,并且尝试使用资源不适合您。理论上,您可以包装iputstream以在出现错误时关闭底层流并重新抛出(或吞下)异常,请注意,如果
getResult()
t出现异常,您没有Result
对象,因此您没有要关闭的对象。最简单和正确的解决方案是使该类可关闭。但如果我无法修改结果(或不想),该怎么办?然后,您将无法使其自动关闭,并且尝试使用资源不适合您。理论上,您可以包装iputstream以在出现错误时关闭底层流并重新抛出(或吞下)异常,请注意,如果getResult()
t出现异常,你没有Result
对象,因此你没有什么可关闭的。最简单和正确的解决方法是使这个类可关闭。@Antoniosss你是对的,复制用于编辑,将我的杯子扔到桌子上,然后取了一些纸巾。也许更值得一提。@Antoniossss你说得对,抄写编辑,把我的杯子扔到桌子上,然后拿了一些纸巾。也许更值得一提。