在C#中,在Dispose
的{{1}}方法中抛出异常是considered错误practice。
相比之下,在java中,IDisposable
的{{1}}方法允许抛出任何异常并强制调用者以某种方式处理它。但如果发生这种情况,合理预期的调用者会怎样做?这表明以某种方式关闭资源的尝试失败了。那么用户在继续之前是否必须尝试再次关闭资源,可能是某种指数退避?
答案 0 :(得分:1)
AutoCloseable
的设计是Java检查异常的结果。有些实现只需要能够抛出已检查的异常,因此需要throws Exception
。但是,implementations should declare more specific types thrown(如果有的话):
虽然声明此接口方法抛出
Exception
,但实施者强烈鼓励声明close
方法的具体实现以抛出更具体的异常,或者抛出no如果关闭操作不能失败,则完全是异常。
如果有办法避免异常,你不应该抛出异常,但你不能总是避免它。例如,当使用未刷新的数据关闭{{3}}时,缓冲的流有两个选项;忽略未写入的数据并关闭或将其写入流,这可能导致异常被抛出。
答案 1 :(得分:1)
因为Java的设计人员能够在实现他们自己的try-with-resources功能之前看到.NET的using
块中的清理 - 异常处理引起的问题,所以他们能够改进它。在.NET中,Dispose
块的作者在吞下任何发生的异常,从而错误地让调用程序认为一切正常,或让异常从Dispose
中渗透出来之间经常面临令人不快的选择。以这种方式消除任何先前例外的任何证据。幸运的是,Java避免了这个问题。
如果try-with-resources块正常成功并且close
也正常成功,则外部代码会正常查看所有内容。如果try
部分发生异常但close
正常成功,则外部代码将看到try-block异常。如果try
正常完成但close
抛出,则外部代码将看到close
异常。如果try
抛出,但close
也抛出,那么外部代码将看到try
异常,但也能够检索close
内发生的任何异常(如果多个嵌套的try-with-resources在close
期间抛出异常,所有抛出的异常都可用于外部代码。)
因此,与.NET设计不同,它常常迫使作者扼杀Dispose
引发的一些潜在严重的异常,Java的设计有利于close
在任何时候充足的情况下抛出异常不应该让来电者相信一切都很好。
答案 2 :(得分:0)
看起来涉及资源的每个操作(包括隐式close()调用)都被视为try {}块的一部分。即使在技术/语法上思考,资源也会在{}括号之外提到。
这意味着如果在close()期间抛出IOException,它将被与你的try相关联的一些catch()子句捕获(或者它将向上传播)。
关于原因为什么可能需要抛出异常:close()可能导致flush(),flush()可能导致write(),而write()可能会失败。