为什么不能在try和catch块之间插入代码?

Rah*_*hul 7 java try-catch

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

你能帮我么...

And*_*san 11

好的,首先是第一件事 - 编译器执行代码,它只是编译它,允许它由JVM运行.

从经验上讲,这没有多大意义,因为如果你有一些代码要放在try块之外但是在catch块之前,那么代码也可以放在try块中.问题是,如果你考虑它,它的行为就像在try块中一样.

我们假设这是有效的Java(这不编译):

try {
    throw new Exception();
}
System.out.println("Sup!");
catch(Exception e) { }
Run Code Online (Sandbox Code Playgroud)

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

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


bdo*_*lan 5

好吧,简单的答案是语言规范禁止这样做。

但是,让我们退后一步,以另一种方式来思考-如果您可以这样做呢?

try {
  foo();
}
bar();
catch (Exception e) {
  baz();
}
Run Code Online (Sandbox Code Playgroud)

这可能是什么语义?如果我们在中捕获到异常foo(),则baz()称为?那bar()呢 如果bar()抛出异常,那么在这种情况下我们会捕获异常吗?

如果例外bar()没有抓住,例外foo()防止bar()运行,那么结构等同于:

try {
  foo();
} catch (Exception e) {
  baz();
}
bar();
Run Code Online (Sandbox Code Playgroud)

如果异常bar() 抓住了,并且例外foo()防止bar()运行,那么结构等同于:

try {
  foo();
  bar();
} catch (Exception e) {
  baz();
}
Run Code Online (Sandbox Code Playgroud)

如果捕获in bar()中的异常,并且in中的异常不会阻止其运行(始终执行),则该构造等效于:foo() bar()bar()

try {
  foo();
} catch (Exception e) {
  baz();
} finally {
  bar();
}
Run Code Online (Sandbox Code Playgroud)

如您所见,此try-try-catch构造的任何合理语义已经可以表达,而无需新的且相当混乱的构造。很难为这种结构设计一个已经不是多余的含义。

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

try {
  foo();
} finally {
  bar();
} catch (Exception e) {
  baz();
}
Run Code Online (Sandbox Code Playgroud)

可能是它不反映实际的执行顺序-catch块 finally块之前运行。这使catch块可以利用finally块以后可能释放的资源(例如,从RPC对象或其他内容中请求其他诊断信息)。可以使它也以其他方式工作吗?当然。这值得么?可能不会。


Kek*_*Kek 4

嗯,它的意思是这样的:

try
{
   somCode();
}
someMoreCode();
catch
{
}
Run Code Online (Sandbox Code Playgroud)

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