为什么变量没有在作用域中的“尝试”中声明,在“捕获”或“最后”中?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (16)

在C#和Java(也可能是其他语言)中,在“try”块中声明的变量不在相应的“catch”或“finally”块中。例如,下面的代码不能编译:

try {
  String s = "test";
  // (more code...)
}
catch {
  Console.Out.WriteLine(s);  //Java fans: think "System.out.println" here instead
}

在这段代码中,catch块中对s的引用发生编译时错误,因为s仅在try块中的作用域中。(在Java中,编译错误是“s无法解析”;在C#中,它是“名称'在当前上下文中不存在”。)

这个问题的一般解决方案似乎是在try块之前而不是在try块内声明变量:

String s;
try {
  s = "test";
  // (more code...)
}
catch {
  Console.Out.WriteLine(s);  //Java fans: think "System.out.println" here instead
}

然而,至少对我来说,(1)这感觉像一个笨拙的解决方案,(2)它导致变量的范围比程序员想要的要大(整个方法的其余部分,而不仅仅是在上下文中的try-catch-最后)。

我的问题是,这个语言设计决策背后的基本原理是什么(在Java中,在C#中,和/或在任何其他适用的语言中)?

提问于
用户回答回答于

两件事情:

  1. 一般来说,Java只有2个级别的范围:全局和功能。但是,try / catch是个例外(不是双关语)。当引发异常并且异常对象获取分配给它的变量时,该对象变量仅在“catch”部分中可用,并在catch完成后立即销毁。
  2. (更重要的是)。您无法知道try块中的异常被抛出的位置。它可能是在你的变量被声明之前。因此,不可能说明catch / finally子句有哪些变量可用。考虑以下情况,其范围如您所示: try { throw new ArgumentException("some operation that throws an exception"); string s = "blah"; } catch (e as ArgumentException) { Console.Out.WriteLine(s); }

这显然是一个问题 - 当你到达异常处理程序时,s不会被声明。考虑到捕获是为了处理异常情况,并且最终必须执行,所以安全并且在编译时声明这是一个问题比在运行时要好得多。

用户回答回答于

你怎么能确定,你已经到达了你的catch块的声明部分?如果实例化引发异常呢?

扫码关注云+社区