java的。在类初始化程序中重新声明类字段和方法嵌套块(框架括号)内的局部变量差异

时间:2014-05-09 10:33:52

标签: java variables methods scope redeclare

我为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
        }
    }
}

1 个答案:

答案 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块 ,并在第二个声明的范围内。无效。