【发布时间】:2018-12-05 13:39:35
【问题描述】:
对于这个代码示例,Java 编译器并不满意:
public class Test1 {
public static void main(String args[]) {
int x = 99;
{
int x = 10;
System.out.println(x);
}
System.out.println(x);
}
}
编译器说:
错误:变量 x 已在方法 main(String[]) 中定义
不过,Java 编译器对此完全满意:
public class Test1 {
public static void main(String args[]) {
{
int x = 10;
System.out.println(x);
}
int x = 99;
System.out.println(x);
}
}
这在 Java 中有点疯狂。当我查看 Java 范围规则时,我几乎总是看到作者描述变量的范围在它们所在的块级别内,除了在实例生命周期内保留其值的对象级变量的实例。
它们都没有以解释 Java 编译器处理此处代码示例的方式来解释规则。但正如我们从这两个明显的例子中看到的那样,范围规则并没有像每个人描述的那样真正起作用。
请有人正确解释一下,以便我正确理解它吗?
【问题讨论】:
-
内部块级别存在于外部范围级别,它已经具有 int(在第一种情况下),在第二种情况下,外部范围级别没有 int(还没有)。
-
不,不。它工作得很好,你可以从内部看到外部,但不能从外部看到内部,就是这样
-
要添加到下面的答案,还有什么替代方法?您似乎认为在第一个示例中,变量 x 的外部定义不应该从内部代码块中可见。
-
对我来说——我的期望是两个代码示例都能很好地编译——即,“内部 x”只是一个完全不同于外部 x 的变量(不管事实如何另一个名为“x”的变量已在外部范围中定义),并且内部块中对“x”的任何引用都是对“内部x”的引用。另一方面,在编译器抱怨我的第一个示例(这是一个从我目前正在处理的更大程序中大量简化的示例)之后,我对编译器接受第二个示例感到相当惊讶。我明白了——但我觉得这很不和谐。
-
它没有什么奇怪或独特之处。范围约束不是双向的。如果一个作用域嵌套在另一个作用域中,则子作用域会从父作用域继承可见性,反之则不然。