<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 類的初始化 #### 初始化順序 首先來看下,當一個類從main入口方法,對于靜態變量、靜態初始化塊、變量、初始化塊、構造器,它們的初始化順序: ``` public class ClassLoadTest { private static User user = new User(); static { System.err.println("static code block"); } { System.err.println("code block"); } private Student student = new Student(); public ClassLoadTest(){ System.err.println("Constructor"); } public static void main(String[] args) { System.err.println("mian ==>"); new ClassLoadTest(); } } class Student{ public Student(){ System.err.println("student initint===>"); } } class User { public User() { System.err.println("user initing===>"); } } ``` 結論: 正常類的加載順序:靜態變量/靜態代碼塊 -&gt; main方法 -&gt; 非靜態變量/代碼塊 -&gt; 構造方法 _**說明:靜態代碼塊與靜態變量的執行順序同代碼定義的順序;非靜態變量與代碼塊的執行順序同代碼執行順序**_ #### 繼承的情況 ``` class Parent { /* 靜態變量 */ public static String p_StaticField = "父類--靜態變量"; /* 變量 */ public String p_Field = "父類--變量"; protected int i = 9; protected int j = 0; /* 靜態初始化塊 */ static { System.out.println( p_StaticField ); System.out.println( "父類--靜態初始化塊" ); } /* 初始化塊 */ { System.out.println( p_Field ); System.out.println( "父類--初始化塊" ); } /* 構造器 */ public Parent() { System.out.println( "父類--構造器" ); System.out.println( "i=" + i + ", j=" + j ); j = 20; } } public class SubClass extends Parent { /* 靜態變量 */ public static String s_StaticField = "子類--靜態變量"; /* 變量 */ public String s_Field = "子類--變量"; /* 靜態初始化塊 */ static { System.out.println( s_StaticField ); System.out.println( "子類--靜態初始化塊" ); } /* 初始化塊 */ { System.out.println( s_Field ); System.out.println( "子類--初始化塊" ); } /* 構造器 */ public SubClass() { System.out.println( "子類--構造器" ); System.out.println( "i=" + i + ",j=" + j ); } /* 程序入口 */ public static void main( String[] args ) { System.out.println( "子類main方法" ); new SubClass(); } } ``` 初始化順序: 父類--靜態變量/父類--靜態初始化塊 子類--靜態變量/子類--靜態初始化塊 父類--變量/父類--初始化塊 父類--構造器 子類--變量/子類--初始化塊 子類--構造器 結論: * 子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了; * 靜態變量、靜態初始化塊順序取決于它們在類中出現的先后順序 * 變量、初始化塊初始化順序取決于它們在類中出現的先后順序 **分析** * \(1\)訪問SubClass.main\(\)\(這是一個static方法\),于是裝載器就會為你尋找已經編譯的SubClass類的代碼(也就是SubClass.class文件)。在裝載的過程中,裝載器注意到它有一個基類,于是再裝載基類。不管你創不創建基類對象,這個過程總會發生。如果基類還有基類,那么第二個基類也會被裝載,依此類推; * \(2\)執行基類的static初始化,然后是下一個派生類的static初始化,依此類推。這個順序非常重要,因為派生類的“static初始化”有可能要依賴基類成員的正確初始化; * \(3\)當所有必要的類都已經裝載結束,開始執行main\(\)方法體,并用new SubClass()創建對象; * \(4\)類SubClass存在父類,則調用父類的構造函數,你可以使用super來指定調用哪個構造函數。基類的構造過程以及構造順序,同派生類的相同。首先基類中各個變量按照字面順序進行初始化,然后執行基類的構造函數的其余部分; * \(5\)對子類成員數據按照它們聲明的順序初始化,執行子類構造函數的其余部分; #### static變量 ``` public class Test { static { i = 0; // 給變量復制可以正常編譯通過 // System.out.print(i); // 這句編譯器會提示“非法向前引用” } static int i = 1; static int j = 1; static{ j = 2; } public static void main(String[] args){ System.out.println(Test.i); //1 System.out.println(Test.j); //2 } } ``` #### 不觸發初始化實例 ``` /** * 被動使用類字段演示一: * 通過子類引用父類的靜態字段,不會導致子類初始化 **/ class SuperClass { static { System.out.println("SuperClass init!"); } public static int value = 123; } class SubClass extends SuperClass { static { System.out.println("SubClass init!"); } } /** * 非主動使用類字段演示 **/ public class NotInitialization { public static void main(String[] args) { // System.out.println(SubClass.value); //SuperClass init! //123 /** * 被動使用類字段演示二: * 通過數組定義來引用類,不會觸發此類的初始化 **/ SuperClass[] sca = new SuperClass[10]; } ``` #### 被動使用類字段 ``` /** * 被動使用類字段演示三: * * 常量在編譯階段會存入調用類的常量池中,本質上沒有直接引用到定義常量的類, * 因此不會觸發定義常量的類的初始化。 **/ public class ConstClass { static { System.out.println("ConstClass init!"); } public static final String HELLOWORLD = "hello world"; } public class Test { public static void main(String[] args){ System.out.println(ConstClass.HELLOWORLD); } } ``` 輸出 ``` hello world ``` 這里沒有初始化ConstClass類,是因為在編譯的時候,常量(static final 修飾的)會存入調用類的常量池【這里說的是main函數所在的類的常量池】,調用的時候本質上沒有引用到定義常量的類,而是直接訪問了自己的常量池 #### 靜態方法調用 當調用目標類的靜態變量或靜態方法時,不會觸發該類的代碼塊或構造方法的執行,示例如下: ``` public class ClassLoadTest { public static void main(String[] args) { // System.err.println(Handler.user); Handler.print(); } } class Handler { public static User user = new User(); static { System.err.println("static code block"); } { System.err.println("code block"); } public Handler(){ System.err.println("Constructor"); } public static void print(){ System.err.println("static method"); } } class User { public User() { System.err.println("user initing===>"); } } ``` ## 參考 {#articleHeader13} java類的初始化順序--[http://blog.sina.com.cn/s/blog\_4cc16fc50100bjjp.html](http://blog.sina.com.cn/s/blog_4cc16fc50100bjjp.html) Java類加載的時機 ——[https://blog.csdn.net/imzoer/article/details/8038249](https://blog.csdn.net/imzoer/article/details/8038249)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看