別整那些虛的,Java構造器,一文帶你瞭解

寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有需要學習的朋友可以Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

理解構造器之前,首先我們需要了解Java中爲什麼要引入構造器,以及構造器的作用。

在很久之前,程序員們編寫C程序總會忘記初始化變量(這真的是一件瑣碎但必須的事),C++引入了 構造器(constructor) 的概念,這是一個在創建對象時被自動調用的特殊方法。Java也採用了構造器。

在這裏插入圖片描述

一、構造器的引入

引入構造器幫助我們解決了哪些問題呢?假設我們每定義一個類都必須定義一個initialize()方法,該方法提醒你,每次使用對象之前都要執行一次該方法,這意味着用戶每次都必須記得自己去調用此方法,這和上文提到的C程序員一樣,很容易就忘記了。Java構造器的出現很好的規避掉了這種問題,創建對象時,java會在使用對象之前調用相應的構造器,保證對象正確初始化。

我們來看一個簡單實例:

public class TestMain {

    TestMain() {    //默認構造器
        System.out.println("默認構造器");
    }

    public static void main(String[] args) {
        new TestMain();
    }
}

//輸出
默認構造器

從這個例子我們看到了,構造器爲 TestMain() ,創建對象時,會分配內存並調用對應的構造方法,可以看到輸出結果爲 默認構造器 ,它已經被正確地初始化了。

二、構造器命名規則

從上面那個例子中或許已經觀察到了:類名和構造器名必須相同,所以”每個方法首字母小寫“的編碼風格並不適用於構造器。

三、注意事項

構造器必須與主類同名
構造器可以有參數
構造器可以重載
沒有返回值
不添加構造器編譯器生成默認構造器

四、默認構造器

默認構造器(又名無參構造器)是沒有形式參數的,它創建的是”默認對象“。舉個栗子:

public class TestMain {
	
	//沒有指定構造器,Java編譯器會自動生成默認構造

    public static void main(String[] args) {
        new TestMain();
    }
}

//輸出

new TestMain() 創建了一個新對象,並調用了默認構造——雖然我們並沒有主動定義它。Java規定了,如果沒有構造會生成默認構造,如果存在了一個及以上的構造便不會自動生成。

public class TestMain {
	
	TestMain(int i) {}
	TestMain(float f) {}

    public static void main(String[] args) {
        TestMain t1 = new TestMain();	//會報錯,沒有對應的構造方法
        TestMain t2 = new TestMain(1);
        TestMain t3 = new TestMain(2.0f);
    }
}

//輸出

new TestMain() 編譯器會報錯,因爲我們沒有定義對應的無參構造方法,編譯器無法順利創建對象。如果你沒有定義構造器,編譯器會認爲”你需要一個構造器,我幫你造一個“;如果你自己寫了一個構造器,編譯器會認爲”你已經有構造器了,你知道自己在做什麼,我不幫你生成“。

五、構造方法重載

有默認無參構造,就有帶參構造;有帶參構造也就會發生方法重載。爲了滿足不同的初始化需求,我們通常會需要定義多個帶參構造器,由於都是構造器,它們的名稱必須相同,爲了讓方法名相同而參數不同的方法存在,我們就必須使用 方法重載 。它是構造器所必須的。

public class TestMain {

    TestMain() {
        System.out.println("默認構造");
    }

    TestMain(int i) {
        System.out.println("int帶參構造");
    }

    TestMain(float f) {
        System.out.println("float帶參構造");
    }

    public static void main(String[] args) {
        TestMain t1 = new TestMain();
        TestMain t2 = new TestMain(1);
        TestMain t3 = new TestMain(2.0f);
    }
}

//輸出
默認構造
int帶參構造
float帶參構造

從上述代碼中我們可以看到,類中定義了三個不同的構造方法, main 方法中,在括號裏傳遞不同的參數,編譯器會根據參數的類型尋找對應的構造方法,從而初始化三個不同的對象,這就是構造方法的重載。

涉及基本類型的重載
在使用構造方法的重載時,我們經常會遇到將基本類型傳遞給重載方法時的一些問題。基本類型可以從一個 較小(窄類型) 類型自動提升(轉型)爲一個 較大(寬類型) 類型,當涉及到方法重載時便會造成一些混淆。舉個栗子:

public class TestMain {

    TestMain(int i) {
        System.out.println("int帶參構造");
    }

    TestMain(long l) {
        System.out.println("long帶參構造");
    }

    TestMain(double d) {
        System.out.println("double帶參構造");
    }

    public static void main(String[] args) {
        TestMain t1 = new TestMain(2.0f);
        TestMain t2 = new TestMain('菌');
    }
}

//輸出
double帶參構造
int帶參構造

首先,我們來看一看 t1 對象,創建對象時傳遞的參數是一個 float 類型的數據,但是結果卻顯示調用了 double帶參構造 ,這是咋回事?其實在創建對象時,編譯器會根據傳遞參數的類型自動尋找參數類型對應的構造方法,如果沒有一模一樣的構造方法,就會尋找類型更“寬”的構造方法。 t1 就是典型的例子, double 類型比 float 更“寬”(float佔4字節,double佔8字節),所以會把傳遞的參數提升。

再來看 t2 對象,這個對象傳遞的是 char 類型數據,對於 char 類型略有不同,如果無法找到恰好接受 char 參數的方法,就會把 char 直接提升爲 int 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章