4

これはジャバです。1 の代入は、クラスがインスタンス化されたときに最初に実行indexされることを理解していますが、なぜこれが有効なのですか?initialization block

public class arr {
    {
        index = 1;
    }

    int index;

    void go() {
        System.out.println(++index);
    }
    public static void main(String [] args){
          new arr().go(); 
        }
    }

出力は 2 です。

symbol not foundコンパイルエラーが発生するはずです。この動作は初期化ブロック固有のものですか? 通常のシナリオでは、のint index;前に来る必要がありますindex = 1;

4

7 に答える 7

5

+1、それは本当に奇妙に見えます。しかし、実際のところ、非静的初期化ブロックは単に javac によってオブジェクト コンストラクターに挿入されます。arr.class を逆コンパイルすると、実際のコードは次のようになります。

public class arr {
    int index;

    public arr() {
        index = 1;
    }

    void go() {
        System.out.println(++index);
    }

    public static void main(String args[]) {
        (new arr()).go();
    }

}

このパズルをもっと楽しくするために

public class A {
    int index;

    A() {
        index = 2;
    }

    {
        index = 1;
    }
}

new A().index とは?. 正解は 2 です。逆コンパイルされた A.class を参照してください

class A {
    int index;

    A() {
        index = 1;
        index = 2;
    }
}

つまり、非静的初期化ブロックがオブジェクト コンストラクターで最初に来る

于 2012-12-30T10:42:53.077 に答える
4

非静的初期化ブロックはコンストラクターの直後に実行されるため、コードは正しく、出力は期待どおりです。

于 2012-12-30T10:36:34.113 に答える
4

コードの順序は関係ありません。あなたが述べているように、

通常のシナリオでは int インデックスです。index = 1 の前に来る必要があります。

これはまさに、フィールドが宣言されてから値 1 が割り当てられることです。コンパイラは、クラス内のこれらの項目の物理的な順序を気にしません。

于 2012-12-30T10:36:51.987 に答える
2

Java チュートリアルから、Java コンパイラは初期化子ブロックをすべてのコンストラクタにコピーします。したがって、このアプローチを使用して、複数のコンストラクター間でコードのブロックを共有できます。

インスタンス変数を初期化するために final メソッドを使用する例を次に示します。

    class Whatever {
        private varType myVar = initializeInstanceVariable();

        protected final varType initializeInstanceVariable() {

            // initialization code goes here
        }
    }
于 2012-12-30T10:38:32.453 に答える
1

Java チュートリアルには次のように記載されています。

クラスは任意の数の静的初期化ブロックを持つことができ、クラス本体のどこにでも表示できます。

さらに、宣言する前に「使用」できる変数と同じです。

class T {

    public static void main(String[] args) {
        T t = new T();
        System.out.println(t.a);
    }

    public int a = 14;
} 
于 2012-12-30T10:40:55.130 に答える
1

一部の言語 (C など) とは異なり、Java ではクラス (静的) 変数とインスタンス変数の宣言の順序は関係ありません。クラス/インスタンス変数は、宣言される前に (テキストで) 参照できます。だからこれでも有効です...

public class X {
   private int a = b;
   private int b = a;
   ...
}

...ただし、イニシャライザは実際には何も役に立ちません。

于 2012-12-30T11:47:47.277 に答える
0

Java は、スタントを実行する前にコードを完全に解析するような言語です (退屈なコンパイラの詳細は避けようとしています)。したがって、イニシャライザ ブロックがフィールドの宣言の前にあるかどうかは関係ありません。物事が行われる特定の順序があります。クラスの読み込み (そしてもちろんフィールドの読み込み)、静的初期化子、コンストラクター、非静的初期化子はすべて、メソッド呼び出しの前に実行されます (静的呼び出しは、コンストラクターと非静的メンバーを実行せずに実行できます)。"K & B" のような SCJP (現在の OCPJP) の本を読んで、内部で何が起こっているのかを本当に理解することを検討してください。「JVM internals」のようなチュートリアルは、この段階ではやり過ぎかもしれません (ただし、後で参照できるようにアーカイブに保管することを検討する必要があります)。

于 2012-12-30T10:50:24.190 に答える