Javaプログラムの実行順序について詳しく理解する
5108 ワード
まずテストをします。
public class Test1 {
public static String name=get();
public Test1() {
}
public static String get() {
System.out.println("Test start");
return "test name";
}
public static void main(String[] args) {
System.out.println("main start");
Test1 bb = new Test1();
}
}
答えは何ですか.
main start
test start
じゃあアウトだ
正解は次のとおりです.
test start
main start
何?mainメソッドから実行されたのではないでしょうか。どうしたんですか。
Javaプログラムの実行時、最初のことはmainメソッドにアクセスしようとすることです.mainはプログラムのエントリに等しいので、mainメソッドがなければプログラムは起動できません.mainメソッドは独立したスレッドを占めています.mainメソッドを見つけたら、mianメソッドブロックの最初の文を実行しますか?答えは必ずしも
分析:
, , 。
mainメソッドが見つかった後、mainメソッドは特殊な静的メソッドであるが、静的メソッドであるため、JVMはmainメソッドが存在するクラスをロードし、クラス内の他の静的部分を見つけようとする.すなわち、まずmainメソッドが存在するクラスを探し、その後、静的変数、静的メソッド、静的コードブロックを含むクラス内の静的コードを順番に実行する.静的メソッドはアクティブに呼び出されないが、ロードされる.静的メソッドの実行が完了すると、動的属性付与とコードブロックを含む動的コードの実行になります.
実行順序の大まかな分類:
1.静的プロパティ、静的メソッド宣言、静的ブロック.
2.ダイナミックプロパティ、一般メソッド宣言、ブロックの構築.
3.構造方法.
1.1静態:
クラスをロードすると、JVMはプロパティのデータ型に基づいてデフォルト値(一挙に生成された)を最初に与えます.その後、静的属性の初期化を行い、静的属性にメモリ空間を割り当て、静的メソッドの宣言、静的ブロックのロード、優先度の区別がなく、出現順に実行され、静的部分は1回しかロードされません.これまで必要なクラスがロードされ、オブジェクトが作成されます.
1.2普通:
newオブジェクトが1つある場合、コンストラクションメソッドが呼び出されますが、コンストラクションメソッドを呼び出す前に(中断されて一時停止しない限り1.1は完了しました)動的プロパティ定義を実行し、デフォルト値(一挙に生成された)を設定します.その後、ダイナミックプロパティの初期化、メモリの割り当て、ブロックの構築、一般的なメソッド宣言(ロードのみ、初期化は必要ありません.呼び出されたときにのみメモリが割り当てられ、メソッドの実行が完了するとすぐにメモリが解放されます)、優先度の区別がなく、出現順に実行されます.最後に、構築メソッドに値を割り当てます.オブジェクトを再作成すると、静的部分は実行されず、通常の部分だけが繰り返し実行されます.
今は少し理解していますか?
最初のテスト問題を分析します。
1、まずjvmはmainエントリを見つけて、クラス全体をロードして2、クラス全体のすべての静的部分を見つけて、静的変数と静的コードブロックを含んで、静的方法、ここでは先にnameを見つけて、get()方法を呼び出したことを発見して、先にget方法を実行して、test startを印刷して、値をnameに返して、実行が終わった後、他の静的変数あるいはコードブロックがないことを発見して、main方法を実行して、main startを印刷します
もう一つのテスト問題があります。
class A {
public A() {
System.out.println("A ");
}
public static int j = print();
public static int print() {
System.out.println("A print");
return 521;
}
}
public class Test1 extends A {
public Test1() {
System.out.println("Test1 ");
}
public static int k = print();
public static int print() {
System.out.println("Test print");
return 522;
}
public static void main(String[] args) {
System.out.println("main start");
Test1 t1 = new Test1();
}
}
実行結果:
A print
Test print
main start
A
Test1
継承関係がある場合は、親の静的部分を先に実行し、子の静的部分を実行し、親の動的部分を実行し、子の動的部分を実行します.
オブジェクトを作成するときは、まずダイナミックプロパティを定義してデフォルト値を設定します.その後、親のコンストラクタが呼び出されます.他のすべては、親のオブジェクトを生成するかどうかにかかわらず、親のオブジェクトを生成するかどうかに依存する可能性があるため、親のコンストラクタが呼び出されます.
最後にもう一つの究極のテスト問題があります。これはアリのかつてのテスト問題です。
public class Text {
public static int k = 0;
public static Text t1 = new Text("t1");
public static Text t2 = new Text("t2");
public static int i = print("i");
public static int n = 99;
public int j = print("j");
{
print(" ");
}
static {
print(" ");
}
public Text(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
public static int print(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
public static void main(String args[]) {
Text t = new Text("init");
}
}
有没有生无可恋???
実行結果:
1:j i=0 n=0
2: i=1 n=1
3:t1 i=2 n=2
4:j i=3 n=3
5: i=4 n=4
6:t2 i=5 n=5
7:i i=6 n=6
8: i=7 n=99
9:j i=8 n=100
10: i=9 n=101
11:init i=10 n=102
まとめ:この手順に従えば、このような問題に遭遇すれば解決できます。
1-3: ,
1-5: ,
1.クラス内のすべての属性のデフォルト値(一挙に)
2.親静的属性の初期化、静的ブロック、静的メソッドの宣言(出現順)
3.サブクラス静的属性初期化、静的ブロック、静的メソッドの宣言(出現順)
4.親の構築方法を呼び出し、
まず、親クラスの非静的メンバーの初期化、ブロックの構築、通常のメソッドの宣言(出現順に実行)
次に、親の構築方法
5.サブクラスの構築方法を呼び出し、
まず、サブクラスの非静的メンバーの初期化、ブロックの構築、一般的なメソッドの宣言(出現順に実行)
次にサブクラスの構築方法
注意:
クラスロード中にインスタンス化プロセス(staticはメソッド、属性、コードブロック、内部クラスを修飾できるため)が呼び出される可能性があります.この場合、クラスロードプロセスを一時停止し、インスタンス化プロセス(中断された)を先に実行し、実行が終了してからクラスロードプロセスを行います.上のアリの試験問題は典型的なクラスロードを一時停止します.
簡単な分析:
1、まず静的部分を実行し、まずk=02、賦値t 1を実行し、t 1がインスタンス化プロセスに関与していることを発見し、まずクラスロードを切断し、インスタンス化プロセス3、インスタンス化プロセスを実行し、クラスの動的部分を実行し、jの賦値であり、printメソッドを実行するので、先にjを印刷し、iとnはいずれも先に0 4、j賦値が完了した後、動的部分を実行し続け、クラスのコードブロックであり、print(「ブロックを構築する」)5、実行が完了すると、動的ブロックがない後にコンストラクション関数が実行され、これでインスタンス化プロセス全体が実行され、t 1付与完了6、t 2がt 1に従って7を実行し、その後i,n 8を付与し、その後静的ブロックを実行し、print(「静的ブロック」)を実行し、これでクラスロードプロセス全体が9に完了し、main関数が実行され、付与t,t,t 1,t 2の実行は同じである