7

我在面试中被问到如果我们将 finally 块放在 try 和 catch 块之间会发生什么我回答在这种情况下编译器会认为没有 catch 块,它将直接执行 finally 块。然后他问为什么不能在 try 和 catch 块之间放置代码?

你能帮我么...

4

5 回答 5

11

好的,首先 - 编译器执行代码,它只是编译它,允许它由 JVM 运行。

从经验上讲,这没有多大意义,因为如果您有一些代码想要放在 try 块之外但在 catch 块之前,那么代码也可以放在 try 块中。问题是,如果您考虑一下,它的行为无论如何都会像在 try 块中一样。

假设这是有效的Java这不会编译):

try {
    throw new Exception();
}
System.out.println("Sup!");
catch(Exception e) { }

当异常被抛出时,打印出来的那一行Sup!仍然会被跳过,因为 JVM 正在搜索跳转到适当的异常处理程序来处理Exception。因此,在某种程度上,代码的行为就像它在 try {} 块本身中一样,这就是为什么它在哪里并不重要,并且 Java 指定这个(现在被证明是无用的)构造是非法的。

现在,如果尝试后的代码本身抛出另一个异常怎么办?如果它是有效代码,它的行为就像原始 try 块中的嵌套 try...catch 块一样。当然,一旦事情开始变得复杂,在 try 和 catch 块之间没有明确联系的方法可能会变得模糊,并且 JVM 最终会不知道哪个 catch/finally 属于哪个 try 块(特别是因为处理程序不必在同一个函数中,甚至在同一个包中!)。

于 2012-07-11T06:46:42.943 回答
5

好吧,轻率的答案是语言规范禁止它。

但是,让我们退后一步,换个角度想一想——如果你做到这一点呢?

try {
  foo();
}
bar();
catch (Exception e) {
  baz();
}

这可能是什么语义?如果我们在 中捕获异常foo(),会baz()调用?怎么样bar()?如果bar()抛出,我们会在这种情况下捕获异常吗?

如果异常 inbar()未被捕获,并且异常 infoo()阻止bar()运行,则该构造等效于:

try {
  foo();
} catch (Exception e) {
  baz();
}
bar();

如果捕获到异常,并且bar() 阻止foo()运行异常bar(),则构造等效于:

try {
  foo();
  bar();
} catch (Exception e) {
  baz();
}

如果异常 in没有bar()被捕获,并且异常 in阻止运行(总是被执行),那么构造等效于:foo() bar()bar()

try {
  foo();
} catch (Exception e) {
  baz();
} finally {
  bar();
}

正如你所看到的,这个 between-try-catch 构造的任何合理语义都已经可以表达,而不需要一个新的——而且相当混乱的——构造。很难为这个结构设计一个不是已经多余的含义。

顺便说一句,我们不能这样做的一个潜在原因是:

try {
  foo();
} finally {
  bar();
} catch (Exception e) {
  baz();
}

可能是它没有反映实际的执行顺序 - catch 块在finally 块之前运行。这允许 catch 块利用 finally 块可能稍后释放的资源(例如,从 RPC 对象或其他东西请求额外的诊断信息)。也可以以另一种方式工作吗?当然。这值得么?可能不是。

于 2012-07-11T08:13:24.873 回答
4

那么它的意思是这样的:

try
{
   somCode();
}
someMoreCode();
catch
{
}

这应该是什么意思?这是不可能的,因为它没有语义,因此语言设计者认为它在语法上是不正确的!

于 2012-07-11T06:43:42.883 回答
0

如果您有 a ,则try必须有catchfinally如 java 语言规范中所定义,14.20 "The try Statement`

于 2012-07-11T06:44:14.103 回答
0

try and catch like .. if and else .. 所以不需要在 try 和 catch 块之间添加代码

于 2012-07-11T06:45:48.703 回答