1

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)

    }
}

常に心に留めていたルールは次のとおりです。3 つのバリアントはすべて可能であり、内部定義は外部と重複すると考えました。

例は、それが間違ったルールであることを示しています。

この状況を明確にし、身近な状況の共通ルールを説明してください。

PS

public class Test {
   int k;
    {
        int k;
        {
            int k;  //java: variable k is already defined in instance initializer of class Test
        }
    }
}
4

1 に答える 1

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

ここで、2 番目のステートメントは、同じ名前を宣言しようとします。同じ名前を、同じ直接囲んでいる 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 ブロックが開始され、ローカル変数が宣言され、フィールドの名前が隠されます (この 2 番目の宣言は有効です)。ここで、ネストされたブロックが宣言され、同じinit ブロックを直接囲む別のローカル変数 (3 番目の宣言) があり、2 番目の宣言のスコープ内にあります。有効ではありません。

于 2014-05-09T11:25:03.780 に答える