try-with-resources 调用 close() 失败
Posted
技术标签:
【中文标题】try-with-resources 调用 close() 失败【英文标题】:try-with-resources fails to call close() 【发布时间】:2015-03-26 10:12:30 【问题描述】:我正在使用方便的 try-with-resources 语句来关闭连接。这在大多数情况下效果很好,但只有在一种非常简单的方法中它不能正常工作。即,这里:
public boolean testConnection(SapConnection connection)
SapConnect connect = createConnection(connection);
try ( SapApi sapApi = connect.connect() )
return ( sapApi != null );
catch (JCoException e)
throw new UncheckedConnectionException("...", e);
sapApi 对象非空,该方法返回 true,但从不调用 sapApi 的 close() 方法。我现在求助于使用 finally 块,它工作正常。但这很令人费解。 Java 字节码还包含对关闭的调用。有没有人见过这种行为?
编辑澄清情况:
这是 SapApi,它当然实现了 AutoCloseable。
class SapApi implements AutoCloseable
@Override
public void close() throws JCoException
connection.close(); // this line is not hit when leaving testConnection(..)
..
以下是与 testConnection(..) 在同一类中的另一个方法。这里 SapApi.close() 在返回之前被调用。
@Override
public List<Characteristic> selectCharacteristics(SapConnect aConnection, InfoProvider aInfoProvider)
try (SapApi sapi = aConnection.connect())
return sapi.getCharacteristics(aInfoProvider);
catch ( Exception e )
throw new UncheckedConnectionException(e.getMessage(), e);
编辑 2: 这是 SapConnect.connect():
SapApi connect()
try
... // some setup of the connection
return new SapApi(this); // single return statement
catch (Exception e)
throw new RuntimeException(e);
SapApi 没有子类。上面的 close 方法只有一种实现。特别是没有空的close()。
【问题讨论】:
为了调用 close(),SapApi 必须实现 Closeable 接口,或者至少实现 java.lang.AutoCloseable。是这样的吗? 不只有 AutoCloseable 是必需的吗? Closeable 扩展了 AutoCloseable。 对,但 AutoClosable 更通用(抛出 java.lang.Exception),在谈论连接时,Closable 更合适,因为它会抛出 IOException。 您的代码无法编译,可能性 #1:如果SapApi
实现了 AutoCloseable,您将需要捕获 IOException
(或者您的方法将使用 throws IOException
声明)。可能性 #2:如果 SapApi
没有实现 AutoCloseable,那么编译器无论如何都会抱怨,因为资源的 try-catch 中只允许自动关闭
AutoClosable 抛出异常而不是 IOException,但你是对的......
【参考方案1】:
为了调用 close(),SapApi 必须实现 AutoCloseable 接口,但是既然我们在谈论连接,那么 SapApi 最好实现抛出 IOException 的 Closable 接口。
阅读: http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html
【讨论】:
SapApi 实现了 AutoCloseable 并且它的 close 方法在同一个类的其他上下文中被调用。【参考方案2】:我不知道你说的是什么
这在大多数情况下都很好用
1 通常SapApi
在 try-with-resources 中使用时会关闭
或
2 它通常适用于SapApi
以外的资源
我是根据数字 2 的假设来回答的。
Try-with-resources 仅适用于 Java 7 中实现 AutoCloseable 接口的资源。所以我的第一个建议是让您检查SapConnect
和SapApi
(无论它们是什么)的API,以确定是否是这种情况。
【讨论】:
在同一个类中有相当多的方法在正确调用 close() 的完全相同的表达式(try-with-resources)中使用 SapApi 类。只有这一种方法不起作用。【参考方案3】:一个猜测:可能connect
返回 SapApi 的子类或代理类。如果没有进行任何更改,close
将被覆盖以不执行任何操作,否则仅调用 super.close()
。
我会给出答案,因为即使没有调用任何方法,AutoCloseable 也可以工作。
【讨论】:
以上是关于try-with-resources 调用 close() 失败的主要内容,如果未能解决你的问题,请参考以下文章
try-with-resources 调用 close() 失败
try-with-resource vs java.lang.IllegalStateException:提交响应后无法调用 sendError()