Java实例化后自动执行_Java的实例化顺序(程序执行顺序)
加載/執行順序:
牢記一點:
靜態和非靜態分開處理
使用到靜態加載時,靜態又分為: 靜態變量, 靜態代碼塊, 其中加載順序是按照類中書寫的先后順序加載的
非靜態加載順序: 按照非靜態書寫順序加載/執行
靜態方法,實例方法只有在調用的時候才會去執行
當靜態加載中遇到需要加載非靜態的情況: 先加載非靜態再加載靜態。
下面兩種情況的加載順序
不涉及到父類子類的情況:
1) 首先將所有靜態成員變量加載進來, 但是不賦值,JVM會根據屬性的數據類型第一時間賦默認值
2)然互再進行賦值,即加載靜態變量一一為分配內存賦值,靜態變量,靜態塊的加載,沒有優先級之分,按照書寫先后順序加載
特殊情況: 靜態變量是加載類本生的實例,會比較麻煩,稍后講解
涉及到父類的情況
父靜態-->子靜態? 加載時不涉及構造方法,只有使用都new才會涉及到構造方法
下面將具體講述程序執行順序
1. main第一句是否先執行
Java程序運行時,第一件事情就是試圖訪問main方法,因為main相等于程序的入口,如果沒有main方法,程序將無法啟動,main方法更是占一個獨立的線程,找到main方法后,是不是就會執行mian方法塊里的第一句話呢?不是
因為main方法雖然是一個特殊的靜態方法,但是還是靜態方法,此時JVM會加載main方法所在的類,試圖找到類中其他靜態部分,即首先會找main方法所在的類。
public class JVMTest {
static{
System.out.println("Main 方法所在靜態代碼塊 static1");
}
public static void main(String[] args) {
System.out.println("main start");
A a = new A();
System.out.println(A.width);
System.out.println(a.width);
}
static{
System.out.println("Main 方法所在靜態代碼塊 static2");
}
}
class A{
public static int width = 100;
static{
System.out.println("靜態初始化類A");
width = 30;
}
public A(){
System.out.println("創建A類的對象");
}
}
結果
Main 方法所在靜態代碼塊 static1
Main 方法所在靜態代碼塊 static2
main start
靜態初始化類A
創建A類的對象
30
30
上例中: 先找到main方法, 然后先加載main 方法所在的類JVMTest的靜態屬性, 靜態代碼塊(按照順序加載),即使靜態代碼塊在main方法下面也要先加載靜態代碼塊。然后執行 main方法
2. 靜態變量聲明一定放在使用前面
3. 父類,子類加載順序
public class JVMParent {
public static int width = 100;
public static int count;
{
System.out.println("parent no static code block :" + count);
}
static{
System.out.println("parent static's count:" + count);
}
JVMParent(int a){
System.out.println("parent init one parameter");
}
JVMParent(){
System.out.println("parent init");
}
}
public class JVMSon extends JVMParent {
{
System.out.println("son no static code block :" + count);
}
static {
System.out.println("son static 1");
}
public static int count1;
JVMSon() {
System.out.println("son init:" + count);
}
static {
System.out.println("son static 2");
}
public static void main(String[] args) {
System.out.println("son main start");
JVMSon a = new JVMSon();
}
}
結果
parent static's count:0
son static 1
son static 2
son main start
parent no static code block :0
parent init
son no static code block :0
son init:0
執行順序:
1)加載Main方法, 先要加載包含Main方法的類, 加載類就先加載父類靜態變量, 靜態代碼塊(按照書寫先后順序)--》 子類靜態變量,靜態代碼塊
2) 執行main方法
3) main 方法中調用有構造函數
父類代碼塊--》 父類構造函數--》子類代碼塊--》子類構造函數
4. 一個比較復雜的例子,如果下面的例子理解了,就撤離理解了Java的執行順序
public class Text {
public static int k = 10;
public int a = print("a");
public static int b = print("b");
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");
public int m = print("m");
{
print("構造塊");
}
static {
print("靜態塊");
}
public int l = print("l");
public static int o = print("o");
public Text(String str) {
System.out.println("構造:" + (++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
public static int print(String str) {
System.out.println("print:" + (++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
public int p = print("p");
public static void main(String args[]) {
Text t = new Text("init");
}
}
print:11:b i=0 n=0
print:12:a i=1 n=1
print:13:j i=2 n=2
print:14:m i=3 n=3
print:15:構造塊 i=4 n=4
print:16:l i=5 n=5
print:17:p i=6 n=6
構造:18:t1 i=7 n=7
print:19:a i=8 n=8
print:20:j i=9 n=9
print:21:m i=10 n=10
print:22:構造塊 i=11 n=11
print:23:l i=12 n=12
print:24:p i=13 n=13
構造:25:t2 i=14 n=14
print:26:i i=15 n=15
print:27:靜態塊 i=16 n=99
print:28:o i=17 n=100
print:29:a i=18 n=101
print:30:j i=19 n=102
print:31:m i=20 n=103
print:32:構造塊 i=21 n=104
print:33:l i=22 n=105
print:34:p i=23 n=106
構造:35:init i=24 n=107
執行順序:
1)JVM 類加載機制中提到,類連接 (驗證, 準備, 解析)中準備工作:
負責為類的類變量(非對象變量)分配內存,并設置默認初始值,準備類中每個字段、方法和實現接口所需的數據結構, 這里說的初始值都是默認的值, 并不是程序中指定的值 , 經過準備工作,類中變量的初始值為如下
k =0; b=0; t1=null; t2=null; i=0; n=0;
2)? JVM在類連接以后進行類的初始化,即給類變量賦值,按照靜態屬性的書寫順序執行
A: public static int k = 10;? ? ?-->? k=10
B:public static int b = print("b");???-->調用print("b")? print:11:b ? i=0? ? n=0
C: public static Text t1 = new Text("t1"); ?當加載靜態變量是需要先加載構造器, 那就轉為先加載所有非靜態屬性
此時按照書寫的順序加載非靜態, 如下所示
public int a = print("a"); --》 print:12:a i=1 n=1
public int j = print("j"); --》print:13:j i=2 n=2
public int m = print("m"); --》print:14:m i=3 n=3
{
print("構造塊"); --》print:15:構造塊 i=4 n=4
}
public int l = print("l"); --》print:16:l i=5 n=5
public int p = print("p"); --》print:17:p i=6 n=6
然后繼續執行構造器
public Text(String str) {
System.out.println("構造:" + (++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
==》構造:18:t1 ? i=7? ? n=7
D:?? ? public static Text t2 = new Text("t2");? 和C的過程一模一樣, 非靜態的每次new都加載一次
print:19:a ? i=8? ? n=8
print:20:j ? i=9? ? n=9
print:21:m ? i=10? ? n=10
print:22:構造塊 ? i=11? ? n=11
print:23:l ? i=12? ? n=12
print:24:p ? i=13? ? n=13
構造:25:t2 ? i=14? ? n=14
E:?? ? public static int i = print("i");? ==>print:26:i ? i=15? ? n=15
F:??? ? public static int n = 99;? ?n=99
G:
static {
print("靜態塊");
}
==>print:27:靜態塊 ? i=16? ? n=99
H:? ? public static int o = print("o");?==>print:28:o ? i=17? ? n=100
I:?Text t = new Text("init");
==>
print:29:a ? i=18? ? n=101
print:30:j ? i=19? ? n=102
print:31:m ? i=20? ? n=103
print:32:構造塊 ? i=21? ? n=104
print:33:l ? i=22? ? n=105
print:34:p ? i=23? ? n=106
構造:35:init ? i=24? ? n=107
參考:?https://www..com/greatfish/p/5771548.html1·
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Java实例化后自动执行_Java的实例化顺序(程序执行顺序)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中string的方法_java中
- 下一篇: 安卓线程同步面试_Android面试题