java - 如何正确关闭输入流?
问题描述
有两种方法可以做同样的事情。首先:
public String getIpByName(String name) {
var builders = NetworkUtil.buildProcess(name);
try (var ip = new BufferedReader(new InputStreamReader(executor.execPipelineAndGetInputStream(builders)))) {
return ip.lines().collect(Collectors.joining());
} catch (IOException exception) {
throw new NotFoundException(name);
}
}
第二:
public String getIpByName(String name) {
var builders = NetworkUtil.buildProcess(name);
try (var result = executor.execPipelineAndGetInputStream(builders)) {
var input = new InputStreamReader(result);
var reader = new BufferedReader(input);
var ip = reader.lines().collect(Collectors.joining());
input.close();
reader.close();
return ip;
} catch (IOException exception) {
throw new NotFoundException(name);
}
哪种方法更正确?
解决方案
第二个永远不正确。这些电话要么close()
很重要,要么不重要。如果它们很重要,它们应该是 try/finally-ied 或 try-with-resourced。如果它们不重要,它们就不重要,你不应该费心写这些陈述。
因此,我们有 3 个备选方案,而不是 2 个,并且只有您的第一个备选方案保持不变:
第二:
public String getIpByName(String name) {
var builders = NetworkUtil.buildProcess(name);
try (var result = executor.execPipelineAndGetInputStream(builders)) {
var input = new InputStreamReader(result);
var reader = new BufferedReader(input);
return reader.lines().collect(Collectors.joining());
} catch (IOException exception) {
throw new NotFoundException(name);
}
}
还有第三个,使用 try-with-resources 的资源链接功能:
public String getIpByName(String name) {
var builders = NetworkUtil.buildProcess(name);
try (var result = executor.execPipelineAndGetInputStream(builders);
var input = new InputStreamReader(result);
var reader = new BufferedReader(input)) {
return reader.lines().collect(Collectors.joining());
} catch (IOException exception) {
throw new NotFoundException(name);
}
}
在这三个选项中,您会进行一些辩论;第一个选项看起来不错;这些所谓的“过滤流”(它们是“包装”另一个流的读取器/写入器/输出流/输入流)的实现具有close()
它们将关闭它们包装的东西的交易。因此,通常#1 看起来不错,但是如果在过滤器流的构造函数中发生异常,那么您就会泄漏资源。会不会出现这些异常?通常不可能,但并非总是如此,这是导致常用过滤器流在构造中崩溃的一种简单方法:
new InputStreamReader(someData, "some non existing charset");
因此,我强烈建议不要使用第一个。剩下2号门和3号门:真的没关系;我认为第二个可能是最易读的,但是第二个选项的问题是各种 IDE 和 linting 工具会抱怨它,他们很难区分代表资源的流和过滤器/内存之间的区别流式样。这不是他们的错,真的:他们怎么可能知道你的execPipelineAndGetInputStream
方法返回的 InputStream 是否应该是“你需要关闭的东西”或“你可以关闭但没关系的东西”或“你不应该关闭的东西”完全没有?
推荐阅读
- c# - 通过 Math Round() 向上和向下舍入
- python - Python 检查两个列表中的重复值和空值并映射它们
- git - 迁移/复制现有的本地 Git 存储库。到 TFS (Visual Studio)
- java - 如何详细计算这段代码的时间复杂度大O?
- selenium - 带有酱实验室连接的 selenium Web 驱动程序中的 java.lang.reflect.InvocationTargetException
- php - 如何在 foreach 循环中回显此 JSON 数据?
- android - 使用 OpenCV 检测账单
- pull-request - 有什么方法可以根据创建日期获取所有拉取请求
- ios - Jitsi - meet framework configuration in iOS
- .net - 站点暴露于 TLSv1.0 并启用了 TLSv1.1