最近、Javaで考えるを読んでいますが、クラス内の各メンバーの初期化に注意を払ったことはありません。間違いがある場合は、修正してください:
何が起こっているかを全体的に把握するには、継承を含む初期化プロセス全体を理解するのが役立ちます。
Java では、各クラスのコンパイルされたコードは独自の独立したファイル (つまり、クラス ファイル) に存在し、プログラム コードが必要な場合にのみロードされます。一般的に、「クラスのコードは初めて使用されるときにロードされます」といいますが、これには通常次の 2 つの状況が含まれます:
クラスの最初のオブジェクトを作成するとき
静的メソッドにアクセスするとき、またはフィールド
注: クラスが初めて使用されるとき、すべてのオブジェクトとコードが書き込まれた順序で初期化されます。静的として定義されたフィールドは 1 回だけ初期化されます。
これ以上のナンセンスはありません。詳細は次のとおりです:
public class Base { //static字段 private static int I1 = printInt("Init I1"); //普通字段 private int i = 11; protected int j; public Base(){ System.out.println("Base constructor"); System.out.println("i="+i+" j="+j); j = 40; } static int printInt(String str) { System.out.println(str); return 10; } } public class Son extends Base{ private static int I2 = printInt("Init I2"); public Son() { System.out.println("Son constructor"); System.out.println("I2="+I2+" j= "+j); } public static void main(String[] args) { Son son = new Son(); } }
このコードを読んだ後、出力は何になると思いますか?
最初に答えを与えてから分析してください:
Init I1 Init I2 Base constructori=11 j=0Son constructorI2=10 j= 40
プログラムはまず Son クラスの main メソッドから開始するため、ローダーが起動して Son のコンパイル済みコード (つまり、クラス ファイル) を見つけます。読み込みプロセス中に、Son にも親クラス Base があることがわかりました。そのため、Base のコンパイル済みコードの読み込みを続けます (Base にまだ親クラスがある場合は、上向きに実行を続けます)。サブクラスは基本クラスに依存するため、クラスが初期化されます。それで何が起こったのかInit I1
, 然后往下到了Son,Son类的static字段初始化,于是发生了Init I2
,到此所有的必要的类加载完成,可以开始初始化对象。看到Son son = new Son()
这行代码,准备调用Son的构造器,我们知道在继承关系中,子类的构造器中会调用super(),当然这里是隐式调用。这样又会回到父类中去,不过在完成构造器之前,父类(Base)中的所有普通字段(即非static字段)都会完成自己的初始化,所以会看到输出i=11 j=0
、次にサブクラス (Son) に来て、実行プロセスは親クラスと同じで、最初に完了します。通常のフィールドを初期化してから、コンストラクター メソッドを呼び出します。
たくさん言いましたが、全体的なプロセスは次のとおりです:
プログラムエントリから開始し、クラス(ここではZクラスとして設定)をロードし、継承関係がある場合は、ルートクラス(ここではクラス A を想定しています)。
クラス A の静的フィールドの初期化を完了し、クラス Z が見つかるまで下方向に再帰します。
クラス A の共通ドメインの初期化を完了し、クラス A のコンストラクターを完了して、クラス Z が見つかるまで下方向に再帰します。
以上がJava の各メンバー変数の初期化プロセスに関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。