staticの実行順序を検討する

3987 ワード

public class Test {         public static void main(String[] args){ System.out.println(OK.i); } }
 
ケース1:class OK{static int i=0;static{int i=5; } }
ケース2:
class OK {  static   { int i=5; }static  int i=0; }
ケース3:
class OK {  static  int i=0;static   { i=5; } }
ケース4:
class OK {  static   { i=5; System.out.println(OK.i);} static  int i=0;
}
ケース1と2は、出力結果が同じで、いずれも0である.ケース3、出力5;ケース4、出力5、0;
 
============================
説明:
・第一static{}とstatic属性の違い、static{}はクラスを初期化する方式であり、多くのことをすることができる.たとえば、オブジェクトの初期化、別のメソッドの呼び出しなどです.静的属性、これはクラスの一部であり、mainメソッドは出力クラスの静的属性であることが重要である.
・1,2の2つの状況が説明しやすいのはstatic{int i=0;}初期化クラスのプロパティではなく、変数を定義するだけで、static{int i=0;int j=i+10;と書き換えます.これは何を意味しますか?この静的ブロックで計算しただけで、あなたの静的属性とは少しも関係ありません.あなたは同名をしていますか.耳障りだから違う名前をつけたほうがいい
・3,4の2つの状況はよりよく説明されています.今回は静的属性を初期化しています.static{i=0}にはintがありません.つまり、新しい変数が定義されていません.このiが静的変数です.jvmが静的なものを処理するのはクラスのロードで一緒に処理されているので、順番に実行するプロセスです.私はこのように言って、あなたが知っているかどうか分かりません. 
以下は状況4の詳細な説明です.
・出力の結果は5,0です.理由は簡単ですね.これは順番に実行されています.ところで、あなたの問題は知っています.^&^あなたは静的属性を後に定義していますが、static{}で初期化することができますか.幸いなことに、私はjvmの虚機のいくつかの知識を見たことがあります.これらのクラスの情報は共通のスタックに配置されており、このクラスを呼び出すと、クラスのすべての情報がメモリにロードされます(もちろんjvmの割り当てと管轄であり、唯一の情報です).
・だからstaticが初期化されたとき、それはすでに存在していたので、int i=0を実行すると5である.の場合は、もちろん0ですが、この場合はi=0が実行されます.実際にはこの属性はメモリに保存されているからです.
・まだ分からない場合は、クラスがメモリにロードされるタイミングを知る必要があります.これは、クラスをコンパイルするたびに、jvmがブラックボックスを作って自動的にクラスのclassに入れます.したがって、最も一般的にクラスをメモリにロードする方法はnewのオブジェクトであり、クラスの静的メソッドや静的プロパティを呼び出すなどの他の方法もあるのでstatic int i=0です.役割はクラスの静的属性を定義する役割であり,int=0で初期化すべきであったがstatic{}はその優先度と同様に高いため,順次実行された.
 
=================================
 
public class StaticInit
{
   static int i;
   int a;
   public StaticInit()
   {
      a=6;
      System.out.println("a  "+a);
   }
   public static void main(String[] args)
  {
    new StaticInit();
  }
  static
  {
     i=5;
     System.out.println("i  "+i);
  }
}
 
 
出力結果:
iの初期化5 aの初期化6
説明:
クラスはstaticメソッドを先に実行し、順番に実行する必要があります.
静的メンバー->静的ブロック->その後、非静的メンバーを最後に再実行してコンストラクション関数を実行します(一般的なシステムでは、パラメータを持たないコンストラクション関数がデフォルトで実行されます).
 
=====================================
    --------Test.java------
public class Test {

 static int i = 1;//  i  

 public void method() {
  System.out.println("Test-  " + i);
 }

 public Test() {
  System.out.println("Test-  " + i);
 }

 static {
  System.out.println("Test-static-first " + i);
  i = 4;//  , 
  System.out.println("Test-static-second " + i);
 }

} 
 
 
-----------SubTest.java------------
 
public class SubTest  extends Test {//  TestStatic 

 static int n = 2;//  n 

 public SubTest() {
  System.out.println("SubTest-  " + n);
 }

 public static void main(String args[]) {
  SubTest t = new SubTest();
  t.method();//  
 }

 static {
  System.out.println("SubTest-static-first " + n);
  n = 3;//  , 
  System.out.println("SubTest-static-second " + n);
 }
} 
 
実行結果:
Test-static-first 1 Test-static-second 4 SubTest-static-first 2 SubTest-static-second 3 Test-構造方法4 SubTest-構造方法3 Test-一般方法4
説明:まずサブクラスのstaticプロパティstatic int n=2を実行します.しかしstaticブロックに続いてnに値を付与し、nが静的であるためn値は永遠に3である.次にmain()関数を実行するとnew()メソッドが現れ、サブクラスの初期化親であるため、iの付与値はnの原理と同じであるため、iの出力は永遠に4である.親初期化はstatic->非static->コンストラクション関数に従い、サブクラスstatic部分が初期化されているため、直接非static->コンストラクション関数->main()のメソッドを実行し続けます.
 ===========================
実行順序に他の問題がある場合は、jdkが持参したツールjavapで確認できます.共通コマンド:javap-c ClassName