最终吞噬了例外
static int retIntExc() throws Exception{ int result = 1; try { result = 2; throw new IOException("Exception rised."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); result = 3; } finally { return result; } }
我的一个朋友是.NET开发人员,目前正在迁移到Java,他问我关于这个来源的以下问题。 理论上,这必须throw IOException("Exception rised.")
retIntExc()
throw IOException("Exception rised.")
并且整个方法retIntExc()
必须throws Exception
。 但没有任何反应,该方法返回2。
我没有测试他的例子,但我认为这不是预期的行为。
编辑:谢谢你的所有答案。 有些人忽略了这个方法被称为retIntExc
的事实,这意味着这只是一些测试/实验示例,显示了抛出/捕捉机制中的问题。 我不需要’修复’,我需要解释为什么会这样。
这就是为什么你不能从C#中的finally块返回:)
这绝对是Java语言规范中规定的行为。 它在14.20.2节中规定 。
如果finally块因为原因S而突然完成,那么try语句突然完成原因S(并且丢弃并抛弃值V的抛出)。
返回是突然完成的一个例子; 如果finally
块抛出exception,那么也会突然完成,丢失原始exception。
上面的引用来自这套嵌套的项目符号,省略了这里不适用的选项:
- 如果try块的执行由于抛出值V而突然完成,那么有一个选择:
- 如果V的运行时类型不能分配给try语句的任何catch子句的参数,则执行finally块。 然后有一个选择:
- 如果finally块因为原因S而突然完成,那么try语句突然完成原因S(并且丢弃并抛弃值V的抛出)。
它将返回2
因为
finally
总是执行
无论抛出什么exception, finally
块都会执行。 它不会在您声明的catch
块捕获exception后执行。 它在try
块之后执行, 如果有则捕获exception 。 如果您的方法抛出exception,除非您在方法中吞下它并返回result
否则它不会返回任何内容。 但你不能兼得。
此外,除非您的方法有任何其他代码,否则也不会遇到ArrayIndexOutOfBoundsException
。
这是因为您在exception传递之前发出了一个return语句,因此返回了一个有效值。 您不能同时返回值并抛出exception。
删除返回周围的finally块将提供您想要的行为。
IOException类不是ArrayIndexOutOfBoundsException类的子类,因此将永远不会执行catch部分。
如果你改变它,它将返回3。
static int retIntExc() throws Exception{ int result = 1; try { result = 2; throw new ArrayIndexOutOfBoundsException ("Exception rised."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); result = 3; } finally { return result; } }
我不明白为什么这不是预期的行为。 到此代码块结束时,结果等于2。
static int retIntExc() throws Exception{ int result = 1; try { result = 2;
然后抛出exception,但是catch块会捕获不同类型的exception,因此不会执行任何操作。
throw new IOException("Exception rised."); } catch (ArrayIndexOutOfBoundsException e) { ... }
保证finally块被执行,所以最后一步是返回2。
这次成功的回报否决了冒泡exception。 如果您希望exception继续冒泡,那么您不能返回finally块。
通过在finally方法中放置return
来覆盖抛出的exception并返回结果。 你的代码应该是这样的:
static int retIntExc() throws Exception{ int result = 1; try { result = 2; throw new IOException("Exception rised."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); result = 3; } finally { // do something } // it gets here only when exception is not thrown return result; }