java 構造器(構造方法)使用詳細說明


知識點

  • 什么是構造器
    構造器通常也叫構造方法、構造函數,構造器在每個項目中幾乎無處不在。當你new一個對象時,就會調用構造器。構造器格式如下:
[修飾符,比如public] 類名 (參數列表,可以沒有參數){
	//這里不能有return
}
  • 默認構造器
    如果沒有定義構造器,則會默認一個無參構造器,這就是為什么你定義了一個對象,比如 People,沒有定義任何構造器卻可以new這個對象,比如 new People() 。如果自定義了構造器,則會覆蓋默認構造器。

  • 如何禁止對象被外部創建
    一些特殊需求,不希望定義的對象被外部創建(典型的就是單例了),那直接將構造器的修飾符改為 private 即可。這樣就不能在外部通過new來創建這個對象了。

  • 構造器重載
    與普通方法一樣,構造器也支持重載。一個對象中是可以支持同時定義多個構造器,通過不同的參數列表來實現重載。經常看到代碼中new一個對象時,有時傳入參數,有時又可以不用傳。比如:new People()跟new People("張三"),這里就是重載了。

  • 構造器的繼承
    子類構造器會默認調用父類無參構造器,如果父類沒有無參構造器,則必須在子類構造器的第一行通過 super關鍵字指定調用父類的哪個構造器,具體看下文例子。final類是不允許被繼承的,編譯器會報錯。很好理解,由於final修飾符指的是不允許被修改,而繼承中,子類是可以修改父類的,這里就產生沖突了,所以final類是不允許被繼承的。

  • 構造器、靜態代碼塊、構造代碼塊的執行順序,詳見下文實例

    • 無繼承的情況下的執行順序
      靜態代碼塊:只在程序啟動后執行一次,優先級最高
      構造代碼塊:任何一個構造器被調用的時候,都會先執行構造代碼塊,優先級低於靜態代碼塊
      構造器:優先級低於構造代碼塊
      總結一下優先級:靜態代碼塊 > 構造代碼塊 > 構造器
    • 有繼承的情況下的執行順序:
      父類靜態代碼塊:只在程序啟動后執行一次,優先級最高
      子類靜態代碼塊:只在程序啟動后執行一次,優先級低於父類靜態代碼塊
      父類構造代碼塊:父類任何一個構造器被調用的時候,都會執行一次,優先級低於子類靜態代碼塊
      父類構造器:優先級低於父類構造代碼
      子類構造代碼塊:子類任何一個構造器被調用的時候,都會執行一次,優先級低於父類構造器
      子類構造器:優先級低於子類構造代碼塊
      總結一下優先級:父類靜態代碼塊 > 子類靜態代碼塊 > 父類構造代碼塊 > 父類構造器 > 子類構造代碼塊 > 子類構造器

實例

1.默認構造器

新建一個類,不提供任何構造器,編譯器會默認提供一個無參構造器,這就是為什么沒定義任何構造器,卻可以new 某個對象()

public class People {
    
}

以上這個People類,可以直接通過 new People()來實例化。

2. 禁止對象被外部創建

如果不希望People在外部通過new People()來實例化,只需要將構造器定義為private

public class People {
    private People(){

	}
}

3.構造器重載

重載可以簡單理解為:同個方法名,不同的參數列表。如果希望People能在外部通過new People() 或 new People("字符串") 來實例化,則通過以下代碼即可

public class People {
    //通過new People()調用
    public People(){

	}
	//通過new People("字符串") 調用
	public People(String str){

	}
}

4.構造器的繼承

定義父類構造器,由於該構造器自定義了一個帶參構造器,覆蓋了默認的無參構造器,所以不能直接 new SuperClass() 調用了,除非再定義一個無參構造器

/**
 * 父類構造器
 */
public class SuperClass {
    /**
	 * 自定義帶參構造器
	 */
    public SuperClass(String str){
        System.out.println("父類的帶參構造方法,參數為:" + str);
    }
}

定義子類構造器,繼承SuperClass,由於SuperClass沒有無參構造器,所以必須在子類構造器中通過 super("字符串")來調用,否則編譯器會報錯

/**
 * 子類構造器
 */
public class SubClass extends SuperClass {
    /**
     * 無參構造器
     */
    public SubClass(){
        //由於SuperClass沒有無參構造器,所以必須在子類構造器中通過 super("字符串")來調用,否則編譯器會報錯。
        //如果沒定義該句,則編譯器會默認調用 super()
		super("");
    }
	/**
     * 帶參構造器
     */
    public SubClass(String subStr){
        //由於SuperClass沒有無參構造器,所以必須在子類構造器中通過 super("字符串")來調用,否則編譯器會報錯。
        //如果沒定義該句,則編譯器會默認調用 super()
		super(subStr);
    }
}

5. 構造器、靜態代碼塊、構造代碼塊的執行順序

5.1 無繼承的情況

public class People {
    
    static {
        System.out.println("靜態代碼塊,程序啟動后執行,只會執行一次");
    }

    /**
     * 默認的無參構造器
     */
    public People(){
        System.out.println("默認構造器");
    }

    /**
     * 構造器重載,自定義一個帶參構造器
     * @param str
     */
    public People(String str){
        System.out.println("帶參構造器,參數:" + str);
    }

    {
        System.out.println("構造代碼塊,每次調用構造方法都會執行一次");
    }
}

實例化People

public static void main(String[] args){
    System.out.println("--------------people----------------");
    People people = new People();
    System.out.println("--------------people1----------------");
    People people1 = new People("張三");
}

執行以上代碼,輸出:

--------------people----------------
靜態代碼塊,程序啟動后執行,只會執行一次
構造代碼塊,每次調用構造方法都會執行一次
默認構造器
--------------people1----------------
構造代碼塊,每次調用構造方法都會執行一次
帶參構造器,參數:張三

5.2 有繼承的情況

定義父類SuperClass

/**
 * 父類構造器
 */
public class SuperClass {

    {
        System.out.println("父類構造代碼塊,每次調用構造方法都會執行的");
    }

    /**
     * 父類無參構造方法
     */
    public SuperClass(){
        System.out.println("父類的默認構造方法");
    }

    /**
     * 重載,自定義父類帶參構造方法
     * @param str
     */
    public SuperClass(String str){
        System.out.println("父類的帶參構造方法,參數為:" + str);
    }

    static {
        System.out.println("父類的靜態代碼塊,程序啟動后執行,只會執行一次");
    }

}

定義子類SubClass,繼承SuperClass

/**
 * 子類構造器,繼承SuperClass
 */
public class SubClass extends SuperClass {

    static {
        System.out.println("子類的靜態代碼塊,程序啟動后執行,只會執行一次,先執行父類的,再執行子類的");
    }

    {
        System.out.println("子類構造代碼塊,每次調用構造方法都會執行的");
    }

    /**
     * 無參構造器
     */
    public SubClass(){

        //這里沒有指定調用父類哪個構造器,會默認調用 super(),調用父類的無參構造器public SuperClass()
    }

    /**
     * 重載構造器,多傳兩個參數
     * @param str
     * @param str1
     */
    public SubClass(String str,String str1){
        //必須寫在構造器第一行,調用父類構造器 public SuperClass(String str)
        super(str);
        System.out.println("子類帶參構造器:" + str1);
    }
}

實例化SubClass

public static void main(String[] args){
    System.out.println("--------------subClass1----------------");
    SubClass subClass1 = new SubClass();

    System.out.println("--------------subClass2----------------");
    SubClass subClass2 = new SubClass("子類第一個參數","子類第二個參數");

}

執行以上代碼,輸出:

--------------subClass1----------------
父類的靜態代碼塊,程序啟動后執行,只會執行一次
子類的靜態代碼塊,程序啟動后執行,只會執行一次,先執行父類的,再執行子類的
父類構造代碼塊,每次調用構造方法都會執行的
父類的默認構造方法
子類構造代碼塊,每次調用構造方法都會執行的
--------------subClass2----------------
父類構造代碼塊,每次調用構造方法都會執行的
父類的帶參構造方法,參數為:子類第一個參數
子類構造代碼塊,每次調用構造方法都會執行的
子類帶參構造器:子類第二個參數

源碼獲取

以上示例都可以通過我的GitHub獲取完整的代碼,點擊獲取


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM