深入研究Java中一个对象的初始化过程
在Java中要想實例化一個對象必須調用構造器,調用構造器這個類必須在jvm已經被加載了,在類加載和對象初始化的過程有些順序問題是值得我們去留意的。
一個Java類中主要包含以下幾部分:
靜態代碼塊:在類加載完的時候就執行可以調用靜態成員,在整個類的生命周期只執行一次,優先于該類中的main方法執行。
靜態屬性、靜態方法:隨著類的加載而加載,類加載了靜態變量靜態方法就存在了,是所有對象所共享的。
構造代碼塊:每次實例化對象都會執行且優先于構造方法。
構造方法:實例化對象是調用。
成員變量:普通變量。
成員方法:普通方法。
這些部分中構造器是必須的,一個類默認有一個無參數的構造器,如果自定義了一個有參數的構造器,那無參構造器就沒了需要顯式的寫出來。
下面我們就來看下,實例化一個對象會經歷那些步驟。
package com.lcx.tj.test; /*** * @author*/ class Father {private String name = "張三";//姓名,顯式賦值初始化private String job = "老師";//職業,顯式賦值初始化//測試默認初始化String String_;Father Father_;byte byte_;short short_;int int_;long long_;float float_;double double_;char char_;boolean boolean_;//靜態代碼塊,在類加載完的時候就執行可以調用靜態成員,在整個類的生命周期只執行一次,優先于該類中的main方法執行。static {System.out.println("Father靜態代碼塊 begin------------");System.out.println("調用靜態方法doSometing");doSometing();sex = "男";System.out.println("Father靜態代碼塊 over------------");}/** 靜態屬性、靜態方法隨著類的加載而加載*/public static final String sex;public static void doSometing(){System.out.println("Father靜態方法doSometing:照顧小孩");}{//構造塊,每次實例化對象都會執行且優先于構造方法System.out.println("Father構造塊");}public Father(){System.out.println("Father無參數構造器"); }public Father(String name, String job) {System.out.println("Father有參數構造器");this.name = name;this.job = job;}//主方法public static void main(String[] args) {System.out.println("Father主方法");/*** 1、類首次加載 靜態屬性靜態方法已經存在,執行靜態代碼塊* 2、實例化對象時 會先執行構造塊 然后調用構造器* 需要注意:* 調用構造器生成對象時,非靜態屬性會先進行賦值初始化,如果沒有賦值就會采取默認初始化,如果是對象默認初始化為null如果是基本類型會初始化為相應的值。* 但是我們在普通的方法中定義了基本類型或者對象沒有進行顯式的賦值初始化就去使用 是會編譯出錯的。*///沒有進顯式的賦值初始化就去使用 會編譯報錯的。 // Father f8 ; // f8.toString(); // int i; // System.out.println(i);Father f1 = new Father();System.out.println("Father toString():"+f1);Father f2 = new Father("李四", "程序員");System.out.println("Father toString():"+f2);}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}@Overridepublic String toString() {return "Father [name=" + name + ", job=" + job + ", String_=" + String_ + ", Father_=" + Father_ + ", byte_="+ byte_ + ", short_=" + short_ + ", int_=" + int_ + ", long_=" + long_ + ", float_=" + float_+ ", double_=" + double_ + ", char_=" + char_ + ", boolean_=" + boolean_ + "]";}}程序運行結果:
如果這個有一個子類呢?在實例化子類對象的時候 順序又是咋樣的呢?那我們接下再瞅瞅。
先看下子類代碼:
class Son extends Father{private String grade;//班級//靜態代碼塊,在類加載完的時候就執行可以調用靜態成員,在整個類的生命周期只執行一次,優先于該類中的main方法執行。static {System.out.println("Son靜態代碼塊");}{//構造塊,每次實例化對象都會執行且優先于構造方法System.out.println("Son構造塊");}public Son() {super();System.out.println("Son無參數構造器");}public Son(String grade,String name,String job) {super(name,job);System.out.println("Son有參數構造器");this.grade = grade;}//靜態屬性public static final String like = "小女孩";//靜態方法public static void doSometing(String a){System.out.println("Son學習");}//主方法public static void main(String[] args) {System.out.println("Son主方法");Son s1 = new Son();System.out.println("Son toString:"+s1);Son s2 = new Son("五年級", "王五", "學生");System.out.println("Son toString:"+s2);}public String getGrade() {return grade;}public void setGrade(String grade) {this.grade = grade;}@Overridepublic String toString() {return "Son [grade=" + grade + ", getName()=" + getName() + ", getJob()=" + getJob() + "]";}}程序運行結果:
最后我們總結一下初始化一個對象要經歷那些步驟,其實很簡單, 如果類是首次加載 就先加載類 然后調用 構造器就OK。
加載類class執行靜態代碼塊-->類構造塊-->類構造器。
如果是子類實例化的話,其實也一樣,只不過 先有父對象在 再才有子對象,所有 先加載父類class再加載子類class 然后 先調用父構造器 再調用子構造器。
加載父類class執行父類靜態代碼塊-->加載子類class執行子類靜態代碼塊-->父類構造塊-->父類構造器-->子類構造塊-->子類構造器。
以上均是個人的一些理解哈,如果有不對的地方敬請指教。
總結
以上是生活随笔為你收集整理的深入研究Java中一个对象的初始化过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 集合(set) 介绍
- 下一篇: react-draft-wysiwyg富