为什么Java没有块范围的变量声明?

以下方法不起作用,因为内部块声明与外部块中的名称相同的变量。 显然,变量属于声明它们的方法或类,而不属于声明它们的块,因此我无法编写一个简短的临时块来进行调试,这会将外部作用域中的变量推送到阴影片刻:

void methodName() { int i = 7; for (int j = 0; j < 10; j++) { int i = j * 2; } } 

几乎我用过的每一种块范围的语言都支持这种语言,包括我在学校编写解释器和编译器的琐碎小语言。 Perl可以做到这一点,就像Scheme一样,甚至是C.甚至PL / SQL都支持这个!

这个Java设计决策的基本原理是什么?

编辑:有人指出,Java确实有块范围。 我问的概念是什么名字? 我希望我能从那些语言设计课程中记住更多。 🙂

我认为理由是大部分时间,这不是故意的,它是一种编程或逻辑缺陷。

在一个像你一样微不足道的例子中,它显而易见,但是在一大块代码中,意外地重新声明一个变量可能并不明显。

ETA:它也可能与java中的exception处理有关。 我认为这个问题的一部分是在一个问题中讨论的,该问题涉及为什么在try / finally范围内没有在try部分中声明的变量。

严格地说,Java 确实具有块范围的变量声明; 所以这是一个错误:

 void methodName() { for (int j = 0; j < 10; j++) { int i = j * 2; } System.out.println(i); // error } 

因为'i'不存在于for block之外。

问题是Java不允许您创建一个变量,该变量与在同一方法的外部块中声明的另一个变量的名称相同。 正如其他人所说,据说这样做是为了防止难以辨认的错误。

因为作者有意这样做并且通过忘记现在有两个具有相同名称的变量而完全搞砸了,这种情况并不少见。 它们更改内部变量名称,但保留使用变量的代码,现在无意中使用了以前隐藏的变量。 这导致程序仍然编译,但执行缓慢。

同样,不小心隐藏变量并改变程序的行为并不罕见。 在不知不觉中遮蔽现有变量可以像在上面提到的那样轻松地改变程序。

允许这种阴影并没有太大的好处,他们认为它太危险了。 说真的,只需将你的新变量称为别的东西,问题就会消失。

我猜,这会导致难以发现的错误。 它与C#类似。

Pascal不支持这一点,因为你必须在函数体上面声明变量。

这个问题的基本假设是错误的。

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%。

另一个原因:如果允许这种变量声明,人们会想要(需要?)一种方法来访问外部块变量。 可能会添加“outer”关键字:

 void methodName() { int i = 7; for (int j = 0; j < 10; j++) { int i = outer.i * 2; if(i > 10) { int i = outer.outer.i * 2 + outer.i; } } }