大多数情况下,我唯一看到的是使用finally块的东西就像是
FileInputStream f;
try{
f= new FileInputStream("sample.txt");
//something that uses f and sometimes throws an exception
}
catch(IOException ex){
/* Handle it somehow */
}
finally{
f.close();
}
我的问题是,如果f的范围以封闭块结束,为什么我们需要在finally中关闭它?
答案 0 :(得分:19)
因为垃圾收集不与资源清理相同。
例如,如果JDBC连接对象超出范围,则没有信号发送到数据库服务器以指示不再需要打开游标和连接。如果没有这些消息,您最终会耗尽可用的游标和连接数。
与文件句柄和任何其他资源相同。在你自己之后清理。
答案 1 :(得分:6)
嗯,你给出了一个糟糕的例子 - 我怀疑你的意思是FileInputStream
- 但基本原因是Java没有确定性的最终确定。
变量 f
的范围以其声明的块(不是try
块)结束,但这并不意味着必然没有“直播” “再次引用该对象 - 垃圾收集器既不会最终确定对象,也不会以任何确定的方式收集垃圾。
除非你想让资源闲置一段任意的时间(并且延迟垃圾收集,因为终结器需要在最终释放内存之前进行额外的收集),你应该明确地关闭资源。
基本上,Java 不以与C ++相同的方式支持RAII;你不应该试着像使用C ++一样使用它。
答案 2 :(得分:2)
因为每次都会调用finally,即使你遇到了异常。 finally块确保文件/连接将被关闭。
答案 3 :(得分:0)
原因是Java不保证一旦对象的特定引用超出范围就会对对象进行垃圾收集。因此,对于引用有限系统资源的对象(例如文件描述符),等待垃圾回收是不够的。
但请注意,java.io.File
实际上不是这样的对象。
答案 4 :(得分:0)
我们最后通过try catch处理异常,最后每次执行都阻塞但是没有catch的保证因为catch块只在参数匹配时传递异常才执行。 例如,如果我们打开任何数据库连接,那么我们必须在离开之前关闭它,必须最终实现。