如果您试图从源头捕获并报告所有异常,那么更好的解决方案是:
ObjectOutputStream oos = null;try { oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(shapes); oos.flush();} catch (FileNotFoundException ex) { // complain to user} catch (IOException ex) { // notify user} finally { if (oos != null) { try { oos.close(); } catch (IOException ex) { // ignore ... any significant errors should already have been // reported via an IOException from the final flush. } }}笔记:
- 标准的Java包装器流,读取器和写入器都传播
close
并传播flush
到它们的包装器流等。因此,您只需要关闭或刷新最外面的包装器。 - 在try块的末尾显式刷新的目的是使(实际)处理程序
IOException
能够看到任何写入失败1。 - 当您对输出流进行关闭或刷新时,由于光盘错误或文件系统已满,可能会出现“一次蓝月亮”的异常。 您不应该压这个异常! 。
如果您经常需要“关闭忽略IOExceptions的可能为空的流”,则可以为自己编写一个帮助方法,如下所示:
public void closeQuietly(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (IOException ex) { // ignore } }}那么您可以将之前的finally块替换为:
} finally { closeQuietly(oos);}(另一个答案指出,
closeQuietlyApache Commons库中已经有一种方法…如果您不介意为项目的10行方法添加依赖项
。UPDATE :请注意,这些方法在2.6版的API。)
但请注意,仅
closeQuietly在 真正 与IO异常无关的流上使用。
1-使用try-with-resources时没有必要。
论问题
flush()与
close()人们的询问:
- 标准的“过滤器”和“缓冲的”输出流和编写器具有API约定,该约定规定
close()
将刷新所有缓冲的输出。您 应该 发现执行输出缓冲的所有其他(标准)输出类的行为也将相同。因此,对于标准类,flush()
在之前立即调用是多余的close()
。 - 对于自定义类和第三方类,您需要进行调查(例如,阅读javadoc,查看代码),但是任何
close()
不刷新缓冲数据的方法都可能 被破坏 。 - 最后,存在
flush()
实际起作用的问题。javadoc说的是这个(用于OutputStream
…)
如果此流的预期目标是底层操作系统(例如文件)提供的抽象,则刷新该流可确保仅将先前写入该流的字节传递给操作系统以进行写入;它不能保证它们实际上已写入到物理设备(例如磁盘驱动器)中。
所以…如果您希望/想象调用可以
flush()保证您的数据将持久存在,那 您就错了!
(如果您需要执行此类操作,请查看
FileChannel.force方法…)
另一方面,如果可以使用Java 7或更高版本,则@Mike Clark的答案中所述的“新” try-with-resources是最佳解决方案。
如果您的新代码未使用Java 7或更高版本,则可能陷入了更深层次的挖掘。



