java. redeclare class field within class initializer and local variable within method nested block(framed braces) differences

StackOverflow https://stackoverflow.com/questions/23562431

Question

I prepare for scjp exam and noticed surprising behaviour for me.

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)

    }
}

Always in my mind I kept following rule: I thought that all three variants is possible and inner definition would overlap external.

example shows that it is wrong rule.

Please clarify this situations and explain common rule for familiar situations.

P.S.

public class Test {
   int k;
    {
        int k;
        {
            int k;  //java: variable k is already defined in instance initializer of class Test
        }
    }
}
Was it helpful?

Solution

Name shadowing is explained in JLS 6.4 Shadowing and Obscuring. I put the relevant parts of it for each of your examples.

Local variables may hide fields

public class Test {
    int f; // field declaration
    { // init block
        int f; // WARNING: Local variable f is hiding a field from type Test 
    }
}

Since this piece of code is declared directly in a class, the first int f; defines a field, and the block is in fact an initializer block. The init block declares a local variable that hides the field's name within that init block. This is valid (but discouraged by a warning).

Local variables may not hide method parameters

public void method (int param){
    int param; // NOT VALID
}

This is not valid because, as the JLS 6.4 clearly states:

It is a compile-time error if the name of a formal parameter is redeclared as a local variable of the method or constructor

Local variables may not hide local variables (in the same "local space")

As the JLS 6.4 states:

It is a compile-time error if the name of a local variable v is redeclared as a local variable of the directly enclosing method, constructor, or initializer block within the scope of v

public static void main(String[] args) {
    int local;
    {
        int local; // NOT VALID: local declaration in same method
    }
}

Here, the second statement tries to declare the same name, as another local variable of the same directly enclosing method, and within the scope of the former declaration. Not valid.

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

Here, the first statement declares a field. Then an init block starts, and a local variable is declared, obscuring the field's name (this 2nd declaration is valid). Now, a nested block is declared, with another local variable (3rd declaration) of the same directly enclosing init block and within the scope of the 2nd declaration. Not valid.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top