我为scjp考试做准备,并注意到了令人惊讶的行为。
public class Test {
int k;
{
int k; // it is valid variant
}
public static void main(String[] args) {
int kk;
{
int kk; // NOT VALID.java: variable kk is already defined in method main(java.lang.String[])
}
}
public void method (int var){
int var;//NOT VALID.java: variable var is already defined in method method(int)
}
}
始终在我的脑海里,我一直遵守规则: 我认为所有三种变体都是可能的,内部定义会与外部重叠。
示例显示这是错误的规则。
请澄清这种情况并解释熟悉情况的常用规则。
P.S。
public class Test {
int k;
{
int k;
{
int k; //java: variable k is already defined in instance initializer of class Test
}
}
}
答案 0 :(得分:1)
JLS 6.4 Shadowing and Obscuring中解释了名称阴影。我为每个例子都列出了它的相关部分。
public class Test {
int f; // field declaration
{ // init block
int f; // WARNING: Local variable f is hiding a field from type Test
}
}
由于这段代码是直接在类中声明的,因此第一个int f;
定义了一个字段,而该块实际上是一个初始化块。 init块声明一个局部变量,该变量隐藏该init块中的字段名称。这是有效的(但警告不鼓励。)
public void method (int param){
int param; // NOT VALID
}
这是无效的,因为JLS 6.4明确指出:
如果形式参数的名称是,则是编译时错误 重新声明为方法或构造函数的局部变量
正如JLS 6.4所述:
如果局部变量v的名称是,则是编译时错误 重新声明为直接封闭方法的局部变量, v
范围内的构造函数或初始化程序块
public static void main(String[] args) {
int local;
{
int local; // NOT VALID: local declaration in same method
}
}
这里,第二个语句尝试声明相同的名称,作为同一 直接封闭方法 的另一个局部变量,并且在前一个声明的范围内。无效。
public class Test {
int f; // field declaration
{ // init block
int f; // VALID: local declaration hiding field
{ // nested local block
int f; // NOT VALID: local declaration in same init block
}
}
}
这里,第一个语句声明了一个字段。然后一个init块启动,并声明一个局部变量,模糊该字段的名称(第二个声明有效)。现在,声明一个嵌套块,使用相同 的另一个局部变量(第三个声明)直接包含init块 ,并在第二个声明的范围内。无效。