closuresJava InputStreams
在使用Java InputStream时,我对使用close()方法有一些疑问。 从我看到并从大多数开发人员那里阅读的内容,您应该总是在不再需要的时候,在InputStream上显式调用close()。 但是,今天我正在研究使用Java属性文件,我发现每个例子都是这样的:
Properties props = new Properties(); try { props.load(new FileInputStream("message.properties")); //omitted. } catch (Exception ex) {}
通过上面的例子,没有办法显式地调用close(),因为InputStream在使用后是不可访问的。 我已经看到了InputStream的许多类似的用法,尽pipe它似乎与大多数人关于明确closures的内容相矛盾。 我通过Oracle的JavaDocs阅读,并没有提到如果Properties.load()方法closuresInputStream。 我想知道这是普遍接受还是更喜欢做更像下面的事情:
Properties props = new Properties(); InputStream fis = new FileInputStream("message.properties"); try { props.load(fis); //omitted. } catch (Exception ex) { //omitted. } finally { try { fis.close(); } catch (IOException ioex) { //omitted. } }
哪种方法更好和/或更高效? 还是真的很重要?
在“ 属性教程 ”中的示例在加载后明确地closures了FileInputStream
,所以我认为可以安全地假设load
方法不负责任。
// create and load default properties Properties defaultProps = new Properties(); FileInputStream in = new FileInputStream("defaultProperties"); defaultProps.load(in); in.close();
仅供参考,我检查了属性的Apache Harmony实现,并且不会在加载时closuresstream。
Properties类将inputstream包装在LineReader中以读取属性文件。 由于您提供了inputstream,因此您有责任closures它。
第二个例子是一个更好的方法来处理这个stream,不要依赖别人来为你closures它。
你可以做的一个改进就是使用IOUtils.closeQuietly()
closuresstream,例如:
Properties props = new Properties(); InputStream fis = new FileInputStream("message.properties"); try { props.load(fis); //omitted. } catch (Exception ex) { //omitted. } finally { IOUtils.closeQuietly(fis); }
我会尝试与资源(至less对于Java 7+):
Properties props = new Properties(); try(InputStream fis = new FileInputStream("message.properties")) { props.load(fis); //omitted. } catch (Exception ex) { //omitted. }
当try块退出时,应该自动调用close()调用。
在文档中没有提到props.load
会closuresinputstream。 你应该像你所build议的那样,在finally块中手动closuresinputstream。
一个函数closures一个InputStream
是不正常的。 相同的约定适用于非垃圾收集语言的内存:如果可能,打开stream的人应closuresstream。 否则,打开一个stream是很容易的(你认为一个函数会closures它,但是它不会,或者是某个东西)
它看起来像第一个代码示例最终依靠FileInputStream中的finalize方法来实际closures文件。 我会说你的第二个例子是更好的,即使在这两种情况下文件确实closures。
有一些像Bytestream那样的情况,close什么都不做,可以省略,否则我认为最好在finally块中closures文件。 如果你打开它,就closures它。
甲骨文网站上有一本名为“ Java平台性能”的书,它在附录中讨论了终结器,它说:
你几乎总是做自己的清理,而不是依靠终结者。 使用终结器也可能会留下不能在无限的时间内恢复的关键资源。 如果您正在考虑使用终结器来确保及时释放重要资源,则可能需要重新考虑。
如果你使用的是Java 7+,你可以使用这个:
try(InputStream is = new FileInputStream("message.properties")) { // ... }
让我给别人的答案增加一点点。
如果你可以导入Apache Commons IO ,那么你可以使用如此方便的AutoCloseInputStream
类:包装你的InputStream
,然后你只需使用你的包装实例,一旦达到input结束就自动closures或当stream明确closures时,以先到者为准。