Java try with resource是否可能无法关闭资源?
根据Oracle文档 try with resources语句是声明一个或多个资源的try语句。资源是一个对象,必须在程序完成后关闭。try with resources语句确保在语句末尾关闭每个资源。任何实现java.lang.AutoCloseable的对象(包括实现java.io.Closeable的所有对象)都可以用作资源 如果资源未实现AutoCloseable,则不能在try块中声明它,必须在主体部分中声明它&必须在finally块中显式关闭。 try-with-resource是否可能无法清理资源,除非您错误地使用习惯用法,例如存在嵌套资源&close()调用对于底层资源不是幂等的? 我的理解是try with resource只能确保close()在幕后被调用,但如果close本身不关闭底层资源,try with resource在清理资源时仍然无效。Java try with resource是否可能无法关闭资源?,java,Java,根据Oracle文档 try with resources语句是声明一个或多个资源的try语句。资源是一个对象,必须在程序完成后关闭。try with resources语句确保在语句末尾关闭每个资源。任何实现java.lang.AutoCloseable的对象(包括实现java.io.Closeable的所有对象)都可以用作资源 如果资源未实现AutoCloseable,则不能在try块中声明它,必须在主体部分中声明它&必须在finally块中显式关闭。 try-with-resource是否
是否有人有相反的观点或更多的澄清?忽略实际不起作用的代码(例如您的示例中的
close()
方法没有实际关闭资源)或完全外部因素,例如人们将调试器连接到侧步清理,我可以想到三种情况,在这种情况下,try-with-resources可能无法清理资源:
- 电源故障、硬件故障、操作系统崩溃或虚拟机崩溃。对于这类事情,没有什么软件可以做,所以它们不在资源处理的范围之内。但是,您仍然需要记住这一点,以防您考虑使用try-with-resources语句来管理诸如强制锁定文件之类的事情
- 异步异常,例如由
生成的异常。如果线程在清理代码中以这种方式“停止”,则清理代码将中止。这种异步异常的不安全性就是为什么Thread.stop()
被替换为Thread.stop()
,这是安全的Thread.interrupt()
- 如果调用了
。这可能被视为上述任何一种情况,但在“正常情况”下可能发生的情况除外System.exit()
在所有其他方面,您应该能够放心,将调用
close()
。使用多个资源进行重试与嵌套的Try块相同,因此引发异常的清理代码不会停止其他清理例程。忽略实际不起作用的代码(如您的示例中的close()
方法没有实际关闭资源)或者完全是外部因素,比如人们将调试器附加到侧步清理上,我可以想到三种情况,在这种情况下,try-with-resources可能无法清理资源:
- 电源故障、硬件故障、操作系统崩溃或虚拟机崩溃。对于这类事情,没有什么软件可以做,所以它们不在资源处理的范围之内。但是,您仍然需要记住这一点,以防您考虑使用try-with-resources语句来管理诸如强制锁定文件之类的事情
- 异步异常,例如由
生成的异常。如果线程在清理代码中以这种方式“停止”,则清理代码将中止。这种异步异常的不安全性就是为什么Thread.stop()
被替换为Thread.stop()
,这是安全的Thread.interrupt()
- 如果调用了
。这可能被视为上述任何一种情况,但在“正常情况”下可能发生的情况除外System.exit()
close()
。使用多个资源重试与嵌套的Try块相同,因此引发异常的清理代码不会停止其他清理例程。是
try (FileSystem fs = FileSystems.getDefault()) {
return fs.getPath(aStringVar);
}
如果FileSystems.getDefault()
返回一个sun.nio.fs.UnixFileSystem
,就像它在使用Java 8 SE的RedHat机器上对我所做的那样,它将在关闭时抛出一个UnsupportedOperationException
。尽管IntelliJ显示了警告并告诉您在使用资源进行尝试时包装这些警告,但您不应该这样做,除非您想处理那个愚蠢的异常。是的
try (FileSystem fs = FileSystems.getDefault()) {
return fs.getPath(aStringVar);
}
如果
FileSystems.getDefault()
返回一个sun.nio.fs.UnixFileSystem
,就像它在使用Java 8 SE的RedHat机器上对我所做的那样,它将在关闭时抛出一个UnsupportedOperationException
。尽管IntelliJ显示了警告并告诉您在使用资源进行尝试时将其包装,但您不应该这样做,除非您想处理那个愚蠢的异常。您能为您认为可能出现故障的情况生成代码吗?这可能归结为“什么时候最后一个块不会运行”(这是非常罕见的,基本上只是在System.exit这样的情况下,它无论如何都不重要)还要注意的是,try-with-resources所做的一切都是调用close
方法。如果该方法正确地完成了它的工作,那是另一个问题。我现在无法生成代码,我在日常编码中没有遇到这个问题,但在一次面试中有人问我&我告诉try-with-resource总是成功的,面试官不相信。你能吗您为您认为可能出现故障的情况生成代码?这可能归结为“最终块何时不运行”(这是非常罕见的,基本上只是System.exit之类的情况,在这种情况下它无论如何都不重要)还要注意的是,try-with-resources所做的一切都是调用close
方法。如果该方法正确地完成了它的工作,那是另一个问题。我现在无法生成代码,我在日常编码中没有遇到这个问题,但在一次采访中有人问我&我告诉try-with-resource总是成功的,采访者对此并不信服。