为什么Java没有块范围变量声明?
以下方法不起作用,因为内部块声明的变量与外部块中的变量同名。显然,变量属于声明它们的方法或者类,而不属于声明它们的块,因此,我无法编写一个简短的临时临时块进行调试,而恰好将外部作用域中的变量压入阴影只是片刻:
void methodName() { int i = 7; for (int j = 0; j < 10; j++) { int i = j * 2; } }
我使用过的几乎每种块范围语言都支持此功能,包括我在学校为解释器和编译器编写的琐碎小语言。 Perl可以做到这一点,Scheme甚至C都可以。甚至PL / SQL都可以做到这一点!
Java做出此设计决定的理由是什么?
编辑:正如有人指出的那样,Java确实具有块作用域。我要问的概念叫什么名字?我希望我能从这些语言设计课程中记住更多。 :)
解决方案
我猜这会导致难以发现的错误。在C#中类似。
Pascal不支持此功能,因为我们必须在函数主体上方声明变量。
我认为其基本原理是,在大多数情况下,这不是故意的,这是编程或者逻辑上的缺陷。
在像我们这样琐碎的示例中,它是显而易见的,但是在一大段代码中,意外地重新声明变量可能并不明显。
预计到达时间:它也可能与Java中的异常处理有关。我认为在与为何在try / final范围中没有在try部分中声明的变量有关的问题中讨论了该问题的一部分。
因为有意识地做到这一点的作者并不罕见,然后忘记了现在有两个具有相同名称的变量,从而完全搞砸了。他们更改了内部变量名称,但保留了使用该变量的代码,该代码现在非故意地使用了先前阴影的变量。这将导致程序仍然可以编译,但可以很好地执行。
同样,意外地阴影变量并更改程序的行为也很常见。像我上面提到的那样,在不知不觉中为现有变量添加阴影可以像更改变量一样容易地更改程序。
允许这种阴影几乎没有什么好处,以至于他们认为它太危险了。认真地说,只要给新变量添加其他名称,问题就会消失。
好吧,严格来说,Java确实有块作用域的变量声明。所以这是一个错误:
void methodName() { for (int j = 0; j < 10; j++) { int i = j * 2; } System.out.println(i); // error }
因为'i'在for块之外不存在。
问题是Java不允许我们使用与在同一方法的外部块中声明的另一个变量相同的名称来创建变量。正如其他人所说,据说这样做是为了防止难以识别的错误。
这个问题的基本假设是错误的。
Java确实具有块级范围。但是它也具有作用域的层次结构,这就是为什么我们可以在for循环中引用i而不在for循环中引用j的原因。
public void methodName() { int i = 7; for (int j = 0; j < 10; j++) { i = j * 2; } //this would cause a compilation error! j++; }
我一辈子都想不通,为什么我们要让作用域以任何其他方式表现。不可能确定在for循环中要引用哪个i
,我敢打赌,我们有99.999%的时间要在该方法中引用i
。