我知道,如果资源实现了AutoCloseable,那么您通过try传递的资源将自动关闭.到现在为止还挺好.但是当我有几个我希望自动关闭的资源时,该怎么办?套接字示例;
try (Socket socket = new Socket()) {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
}
Run Code Online (Sandbox Code Playgroud)
所以我知道套接字将被正确关闭,因为它在try中作为参数传递,但输入和输出应如何正确关闭?
java sockets datainputstream try-with-resources autocloseable
try-with功能如何适用于AutoCloseable
已声明的变量null
?
我假设这会在尝试调用close
变量时导致空指针异常,但它运行没有问题:
try (BufferedReader br = null){
System.out.println("Test");
}
catch (IOException e){
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud) java.lang.AutoCloseable的close()方法的Java文档说
__PRE__
它们是什么意思是幂等方法,以及两次调用这个close()方法的副作用是什么?并且由于接口Closeable扩展了AutoCloseable,为什么在Closeable接口结束时不能看到副作用?
我读到catch
try-with-resources 中的块是可选的.我尝试Connection
在try-with-resources块中创建一个对象,没有后续catch
块,只是为了从eclipse中获取编译器错误:" SQLException
自动close()
调用引发的未处理异常类型."
由于可以在try-with-resources中使用的每个资源都实现AutoCloseable
,因此在调用close()
方法时可能抛出异常,我不明白该catch
子句是如何可选的,因为它不允许我跳过捕获异常close()
.
是否有一些特殊要求,具体实现AutoCloseable
不直接声明其close()
方法中抛出的任何异常?(如覆盖AutoCloseable
的close() throws Exception
一个close()
不抛出任何异常)?
..或者这可能只是一个日食问题?
编辑:这是仍然触发问题的最简单的代码片段:
try (Connection con = dataSource.getConnection()) {
/*...*/
}
Run Code Online (Sandbox Code Playgroud)
关于这是否与使用JNDI数据源有关的想法?
提前致谢.
我正在创作一个java库.一些旨在由库用户使用的类保存本机系统资源(通过JNI).我想确保用户"处置"这些对象,因为它们很重,并且在测试套件中它们可能导致测试用例之间的泄漏(例如,我需要确保TearDown
将丢弃).为此我使Java类实现了AutoCloseable,但这似乎不够,或者我没有正确使用它:
我不知道如何使用try-with-resources
在测试的情况下(我使用的语句JUnit5
有Mockito
),在"资源"是不是短命的-这是测试夹具的一部分.
像往常一样勤奋,我尝试finalize()
在那里实现和测试闭包,但事实finalize()
证明甚至没有调用(Java10).这也被标记为已弃用,我确信这个想法不会受到诟病.
这是怎么做到的?要清楚,如果他们不调用close()
我的对象,我希望应用程序的测试(使用我的库)失败.
编辑:添加一些代码,如果它有帮助.它并不多,但这正是我想要做的.
@SuppressWarnings("deprecation") // finalize() provided just to assert closure (deprecated starting Java 9)
@Override
protected final void finalize() throws Throwable {
if (nativeHandle_ != 0) {
// TODO finalizer is never called, how to assert that close() gets called?
throw new AssertionError("close() was not called; native object leaking");
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2,赏金的结果感谢所有的回复,一半的赏金被自动授予.我的结论是,对于我的情况,最好尝试解决方案Cleaner
.但是看起来,虽然已经注册,但是不会调用清理操作.我在这里问了一个跟进问题.
该Closeable
接口是在Java 5中引入的,而AutoCloseable
接口是在Java 7中与try-with-resources
语句一起引入的.Closeable
扩展(自Java 7以来)Autocloseable
接口.
在OCA/OCP Java SE 7 - 程序员I和II学习指南中,它在第399页上说:
如果我们打
close()
多次电话会发生什么?这取决于.对于实现的类,实现AutoCloseable
必须是幂等的.这意味着你可以close()
整天打电话,第二次及以后什么都不会发生.[...]对于实施的课程,Closeable
没有这样的保证.
所以根据这个文本,实现AutoCloseable
需要是幂等的,而Closeable
不是.现在,当我AutoCloseable
在docs.oracle.com上查看界面文档时,它说:
请注意,与
close
方法不同Closeable
,此close方法不需要是幂等的.换句话说,close
多次调用此方法可能会产生一些可见的副作用,Closeable.close
如果多次调用则需要不起作用.
现在这与书中所写的相反.我有两个问题:
(1)什么是正确的?docs.oracle.com上的文档还是书?这两个接口中的哪一个需要幂等性?
(2)无论哪一个都需要是幂等的 - 我是否正确Java实际上根本没有办法确保它是幂等的?如果是这样,那么close
方法的" 幂等"的"要求" 是程序员应该做的事情,但我永远不能确定使用该界面的人确实这样做了,对吧?在这种情况下,幂等仅仅是oracle的建议,对吗?
今天我试着重构这个代码,它从目录中的文件中读取id,
Set<Long> ids = new HashSet<>();
for (String fileName : fileSystem.list("my-directory")) {
InputStream stream = fileSystem.openInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = br.readLine()) != null) {
ids.add(Long.valueOf(line.trim()));
}
br.close();
}
Run Code Online (Sandbox Code Playgroud)
使用流api
Set<Long> ids = fileSystem.list("my-directory").stream()
.map(fileName -> fileSystem::openInputStream)
.map(is -> new BufferedReader(new InputStreamReader(is)))
.flatMap(BufferedReader::lines)
.map(String::trim)
.map(Long::valueOf)
.collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
然后我发现IO流不会被关闭,我没有看到一种简单的方法来关闭它们,因为它们是在管道内创建的.
有任何想法吗?
upd:示例中的FileSystem是HDFS,Files#lines
不能使用类似的方法.
我是新手Java8
,我想知道,对于AutoCloseable
资源,我是否必须try
为每个添加一个resource
,或者它将使用上面的代码
try (Connection conn = getConnection();) {
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery(sql);
while (rset.next()) {
TelefonicaDataVO vo = new TelefonicaDataVO();
vo.setTelefonicaDataId(rset.getString("Telefonica_PSD_ID"));
vo.setReceptionDate(nvl(rset.getTimestamp("CREATION_DATE")));
vo.setMessage(nvl(rset.getString("MESSAGE")));
ret.add(vo);
}
}
Run Code Online (Sandbox Code Playgroud) 我在Eclipse中获得AutoCloseable
的这些"资源泄漏"警告似乎可以节省生命.
但是,如何让它们为工厂创建的实例工作?
例如(a
有效,但b
没有):
public static void main(String[] args) {
// a) This emits a warning
new AutoCloseable() {
@Override
public void close() throws Exception {}
};
// b) But this doesn't!
newResource();
}
public static AutoCloseable newResource() {
return new AutoCloseable() {
@Override
public void close() throws Exception {}
};
}
Run Code Online (Sandbox Code Playgroud)
是否有我可以坚持的注释newResource()
或我可以做的事情让编译器(或者它是Eclipse?)知道所有权的变化?
我使用CloseableHttpResponse(来自Apache的HttpClient的-4.5.3),我不知道我使用的是正确的,我看到了一个不带票的答案用EntityUtils.consume
最后在:
Run Code Online (Sandbox Code Playgroud)CloseableHttpResponse response1 = httpclient.execute(httpGet); try { System.out.println(response1.getStatusLine()); } finally { EntityUtils.consume(response1.getEntity());
CloseableHttpClient
是抽象的,没有 close 方法可以调用,尽管在这个答案中使用了它:
CloseableHttpResponse response = httpclient.execute(httpget);
try {
//do something
} finally {
response.close();
}
Run Code Online (Sandbox Code Playgroud)
目前我正在使用 tryCloseableHttpClient
和CloseableHttpResponse
send 方法内部的资源。
我没有错过任何打开的资源或以错误的方式使用它吗?
private CloseableHttpResponse send()
throws URISyntaxException, UnsupportedEncodingException, IOException, ClientProtocolException {
URIBuilder uriBuilder = new URIBuilder(BASE_URL);
HttpHost target = new HttpHost(uriBuilder.getHost(), uriBuilder.getPort(), uriBuilder.getScheme());
HttpPost post = new HttpPost(uriBuilder.build());
try (CloseableHttpClient httpClient = HttpClients.custom().build(); CloseableHttpResponse response = httpClient.execute(target, post)) { …
Run Code Online (Sandbox Code Playgroud) autocloseable ×10
java ×10
idempotent ×2
dispose ×1
eclipse ×1
finalize ×1
java-8 ×1
java-io ×1
java-stream ×1
oracle ×1
sockets ×1
try-catch ×1