2016-09-09 4 views
2

classが「読み込まれています」とはどういう意味ですか?classはjavaにいつロードされますか?

例えば、クラスローディング時にStatic initブロックが実行されていると言われています。正確にclassがロードされたら?

キャシーシエラの本から、このコードを参照してください。

class Bird { 
    { 
     System.out.print("b1 "); 
    } 
    public Bird() { 
     System.out.print("b2 "); 
    } 
} 

class Raptor extends Bird { 
    static { 
     System.out.print("r1 "); 
    } 
    public Raptor() { 
     System.out.print("r2 "); 
    } 
    { 
     System.out.print("r3 "); 
    } 
    static { 
     System.out.print("r4 "); 
    } 
} 

class Hawk extends Raptor { 
    public static void main(String[] args) { 
     System.out.print("pre "); //1 
     new Hawk();//2 
     System.out.println("hawk "); 
    } 
} 

上記のコードの出力は次のとおりです。 R1〜R4事前B1、B2、R3 R2鷹

私はhowcomeの前が印刷されて理解していカントr1の後。コードのどの部分がRaptorクラスをロードしましたか?答えの

一つは言う:

「クラスが最後の可能な瞬間に初期化されますが、そのメンバーのいずれかの前にアクセスされます」。

しかし、そのロジックによって、r1より前に印刷されるべきではありませんか? 2行目はline1の実行後にRaptorクラスのコンストラクタにアクセスするためです。

+0

「ロード済み」という定義にはなりませんか? – byxor

+0

クラスは、そのクラスへの参照を持つことができるときに読み込まれます。初期化は、しばしば一緒に行われる後のステップですが、必ずしもそうする必要はありません。 –

+0

@PeterLawrey main()メソッドの実行開始前に起こっていますか? – SKG

答えて

4

は実装固有であるクラスロード、非常に厳密に指定されたクラス初期化を、混同しないでください。残念ながら、これらの2つの用語は、同じことを意味するようにしばしば使用されますが、通常、クラスローディングの時間は、クラスの初期化の時間を指します。

詳細なケースバイケースルールのエグゼクティブサマリーとして、クラスは最後の可能な時点で初期化されますが、そのメンバーにアクセスする前に初期化されます。

この部分をクリアして、例のコードには、クラスHawk extends Raptor extends Birdがあります。 Hawkは、プログラムのエントリポイントを含むクラスです。メソッドはmainです。これは初期注文です。

  1. Hawkを初期化します。親クラスRaptorは初期化されていますか?いいえ。
  2. Raptorの初期化を開始します。その親のBirdは初期化されていますか?いいえ。
  3. Birdの初期化を開始します。
  4. Birdを完全に初期化します。
  5. Raptorの静的initブロックを実行します。これはr1 r4を印刷します。
  6. Raptorを完全に初期化します。
  7. Hawkを完全に初期化します。
  8. Hawk.main()の実行を開始します。これはpreを印刷します。
+0

こんにちはマルコ、私は質問を編集しました。もう一度見てもらえますか? – SKG

+0

私は答えを編集しました。 –

+0

ありがとうございます。私は完全にコンストラクターチェインを見逃していました。しかし、私はあなたの5番目のポイントは編集でより完全になると思う:Raptorの "静的な" initブロックを実行する。 – SKG

0

通常、初めてクラスを使用しようとすると、インスタンスを作成しようとするか、静的メソッドの1つを使用するか、クラスのClass<?>オブジェクトへの参照を格納してください。

これは、クラスローダーの実装によって異なる場合があることに注意してください。

0

異なるJVMはさまざまな方法でクラスをロードしますが、基本ルールは必要なときにクラスをロードすることだけです。ロードされたクラスによって必要とされる他のクラスがある場合、それらもロードされます。ロードプロセスは再帰的です。

以下のコードは、クラスと静的ブロック、変数laodingの簡単な例です。上記のプログラムのための

public class Foo { 

    //instance variable initializer 
    String s = "abc"; 

    //constructor 
    public Foo() { 
     System.out.println("constructor called"); 
    } 

    //static initializer 
    static { 
     System.out.println("static initializer called"); 
    } 

    //instance initializer 
    { 
     System.out.println("instance initializer called"); 
    } 

    public static void main(String[] args) { 
     new Foo(); 
     new Foo(); 
    } 
} 

出力:

static initializer called 
instance initializer called 
constructor called 
instance initializer called 
constructor called 
+0

main()メソッドが完全に空の場合。それはまだ "静的イニシャライザ"と呼ばれています。どの時点でFooクラスが読み込まれていますか? – SKG

+0

main()メソッドがFooクラスに存在します。プログラムを実行しようとすると、プロジェクトの開始点、すなわちmain()メソッドが見つかることから始まります。このシナリオではmain()メソッドがFooクラスにあります。 Classloaderはmainメソッドを実行するためにFooクラスをメモリにロードします。だからFooクラスをメモリにロードしている間は、静的ブロックや変数などの他のパラメータもロードされます – Abhijeet

関連する問題