詳細なJavaの静的コードブロック、コードブロックの非静的、スタティックメソッド、コンストラクタ、コードブロック構造

Javaベースの学生は確かに、なぜ何の実装、後に、この小さな丘の中腹、静的コードブロック、コードの非静的ブロック、静的メソッド、コンストラクタ、建設コードブロック、これらの、最初の実行の周りに開いていませんでしたか?

まず、次のポイント、そして証拠コードで始まり、最終的にメカニズムを探ります。

Javaクラスのロード順序

1、それが最初にロードするJavaクラスは、インスタンスの初期化2一度、静的初期化ブロックの静的メンバ変数、静的メソッドを持っている、とあなたは新しいメソッドがクラス3が作成されます呼び出すときにのみ、クラスのインスタンスの作成プロセスは、仮想マシン:彼の息子によると継承関係の初期化は、最初の親クラスの初期化ブロック部分は、親クラスのコンストラクタを実行すると、このクラスは、初期化ブロックのサブクラスを継承実行し、最終的にコンストラクタサブクラス4、第破壊サブ破壊クラスインスタンスクラスセクション、その後、親クラスの一部の破壊

非静的コードブロックは、オブジェクトがインスタンス化されるたびに呼び出されます。何が新しいオブジェクトの後に起こる:オブジェクトのインスタンス変数に(「定数」ではない)メモリ領域を割り当て、メンバ変数のデフォルトの初期化、初期メンバ変数の宣言、初期化初期化ブロック(また、コードブロックまたは静的構成コードブロックと呼ばれます) ;コンストラクタの初期化。

サンプルコード

public class Test01 {
    public static void main(String[] args) {
        B b = new B();
    }
}
class B extends A{
    static{
        System.out.println("子类的静态代码块");
    }
    C c = new C();
    {
        System.out.println("子类的构造代码块");
        C.method();
    }
    B(){
        System.out.println("子类的构造方法");
    }
}
class A{
    static{
        System.out.println("父类的静态代码块");
    }
    C c = new C();
    A(){
        System.out.println("父类的构造方法");
    }
}
class C{
    static public  void method(){
        System.out.println("C的静态方法");
    }
    static{
        System.out.println("C类的静态代码块");
    }
    C(){
        System.out.println("C的构造方法");
    }
}

コード実行中の結果:

父类的静态代码块
子类的静态代码块
C类的静态代码块
C的构造方法
父类的构造方法
C的构造方法
子类的构造代码块
C的静态方法
子类的构造方法

解釈:
あなたはJavaクラスをロードする最初の時間、静的な初期化ブロックの静的メンバ変数、時間の初期化の静的メソッドがあり、BはAを継承するには、最初の静的コードブロックBを実行しなければならなかったが、親子関係に応じて初期化され、Aは、プラグを追加しました最初の静的ブロック、プリント「コード親クラスの静的ブロック」を実行し、静的ブロックBもロードされ、プリント「コードサブクラスの静的ブロック」;親クラスクラスCにも負荷が静的、来、C新しい時間「コードクラスCの静的ブロック」を印刷するコードのブロック、構成方法は、「設定方法Cを」印刷実行し、その後、コンストラクタメソッドaを実行し、印刷「設定親クラス」;次いでクラスBは、下方Cと新しい印刷「設定方法C」を継続し、その後、コードブロックの非静的下方印刷「設定コードブロックサブクラス」および「静的メソッドC」を実行し、最後にBクラスの実行、印刷のコンストラクタ「コンストラクタサブクラス。」

メカニズム

特定のメモリをロードするためにどのように、一時的に、TODOを読む時間がない、ので、Javaのクラスローディング機構は、さらに詳細な議論を参照。

逆コンパイルの結果によると、全体のプロセスは次のように実行されます:

public class Test01 {
    public static void main(String[] args) {
        B b = new B();
    }
}
class B extends A{
    static{
        System.out.println("子类的静态");
    }
    C c ;

    B(){
        super();
        c = new C();
        System.out.println("子类的构造代码块");
        C.method();
        System.out.println("子类的构造方法");
    }
    public void method(){
        System.out.println("子类的成员方法");
    }
}
class C{
    static public  void method(){
        System.out.println("C的静态方法");
    }
    static{
        System.out.println("C类的静态");
    }
    C(){
        super();

        System.out.println("C的构造方法");
    }
}
class A{
    static{
        System.out.println("父类的静态");
    }
    C c ;
    A(){
        super();
        c = new C();
        System.out.println("父类的构造方法");
    }
}

工法、前のスーパー()は、メンバ変数(C =新しいC())、その後、他のコードは、動作が完了し、順次読み出します。これは、実メモリの運用ルールです。

スプレッド

私は出力が何であるかを尋ねることがあり、次の質問を見てください

public class Test03 {
    public static void main(String[] args) {
        Zi zi = new Zi();
    }
}
class Zi extends Fu{
    public int count=3;
    public Zi(){
    }
    public void print(){
        System.out.println("Zi..."+count);
    }
}
class Fu{
    public int count=10;
    public Fu(){
        print();
    }
    public void print(){
        System.out.println("Fu..."+count);
    }
}

次のように論理前述のように、変換コードの後です。

public class Test03 {
    public static void main(String[] args) {
        Zi zi = new Zi();
    }
}
class Zi extends Fu{
    public int count=0;//默认初始值为0
    public Zi(){
        super();
        count=3;
    }
    public void print(){
        System.out.println("Zi..."+count);
    }
}
class Fu{
    public int count=0;
    public Fu(){
        super();
        count=10;
        print();
    }
    public void print(){
        System.out.println("Fu..."+count);
    }
}

紫ZI =新しい紫()、最後のコンストラクタサブクラスを見つけ、スーパー()、このタイムカウントまたはサブクラス0、親クラスの親クラスのコンストラクタを見つけ、10の数、印刷()、サブ彼らは自分自身のサブクラスを見つける必要があるクラスを書き換え、この時点では独自のサブクラス、または0を見つけるにも数え、結果Zi...0

おすすめ

転載: blog.csdn.net/wjl31802/article/details/90199020