C ++ 引入了構(gòu)造器(constructor,也叫構(gòu)造函數(shù))的概念,它是在創(chuàng)建對象時被自動調(diào)用的特殊方法。 Java 也采用了構(gòu)造器,并且還提供了一個垃圾收集器(garbage collector),當(dāng)不再使用內(nèi)存資源的時候,垃圾收集器會自動將其釋放。
構(gòu)造器定義
在 Java 中,可以通過編寫構(gòu)造器來確保每個對象的初始化。但是這里有兩個問題:
這個構(gòu)造器使用的任何名字都有可能與類里某個成員相沖突;
編譯器負責(zé)調(diào)用構(gòu)造器,所以它必須始終知道應(yīng)該調(diào)用哪個方法。
C++ 語言采用的方案就是將構(gòu)造器和類的名字定義相同,Java 也采用了這個方案。 構(gòu)造器的作用是用來建立一個新的類的實例,當(dāng)一個對象被創(chuàng)建時,JVM 使用一個構(gòu)造函數(shù),并為其分配內(nèi)存空間。
語法結(jié)構(gòu)
?
class ClassName { ClassName() { } }
?
例如,在下面的示例中,我們創(chuàng)建了一個名為 ReLearnConstructor 的構(gòu)造函數(shù)。在構(gòu)造函數(shù)內(nèi)部,我們正在初始化 hello 變量的值。:
?
public class ReLearnConstructor { String hello; // 屬性 // 構(gòu)造器 public ReLearnConstructor() { hello = "Hello, Constructor!"; } public static void main(String[] args) { ReLearnConstructor rc = new ReLearnConstructor(); System.out.println(rc.hello); } }
?
注意創(chuàng)建 ReLearnConstructor 類的對象的語句:ReLearnConstructor rc = new ReLearnConstructor ();
在這里,當(dāng)創(chuàng)建對象時,調(diào)用 ReLearnConstructor 構(gòu)造函數(shù)。并且,hello 變量的值被初始化。
因此打印的 hello 的值為:
構(gòu)造器目的
構(gòu)造函數(shù)的目的是初始化對象的狀態(tài),為所有聲明的屬性賦值。如果我們沒有自定義構(gòu)造函數(shù),JVM 就會為這些屬性分配默認值。 原始類型的默認值:
整數(shù)類型是 0
浮點類型是 0.0
布爾類型是 false
對于其他 Java 引用類型,默認值是 null,這意味著引用類型的屬性沒有被分配任何值。 后面可以用代碼查看這些默認值。
構(gòu)造器分類
在 Java 中,有三種類型的構(gòu)造器:
無參構(gòu)造器
有參構(gòu)造器
默認構(gòu)造器
無參構(gòu)造器
與方法類似,Java 構(gòu)造函數(shù)可能有參數(shù),也可能沒有任何參數(shù)。如果構(gòu)造函數(shù)不接受任何參數(shù),則稱為無參數(shù)構(gòu)造器。例如上述代碼中 ReLearnConstructor 構(gòu)造器就是:
// 無參構(gòu)造器 public ReLearnConstructor() { hello = "Hello, Constructor!"; }
?
有參構(gòu)造器
字面理解,具有參數(shù)的構(gòu)造函數(shù)稱為有參數(shù)構(gòu)造器。那為什么需要使用有參構(gòu)造器? 有參構(gòu)造器可用于為不同對象提供不同初始化的值。?例如:
public class ReLearnConstructor { String languages; // 接受單個參數(shù)的構(gòu)造器 public ReLearnConstructor(String lang) { languages = lang; System.out.println("我在學(xué)習(xí) " + languages + " 語言!"); } public static void main(String[] args) { // 向構(gòu)造器中傳入不同的值 ReLearnConstructor rc1 = new ReLearnConstructor("Java"); ReLearnConstructor rc2 = new ReLearnConstructor("Go"); ReLearnConstructor rc3 = new ReLearnConstructor("Python"); } }運行結(jié)果:
?
默認構(gòu)造器
如果我們不創(chuàng)建任何構(gòu)造函數(shù),Java 編譯器會在程序執(zhí)行期間自動創(chuàng)建一個無參數(shù)構(gòu)造函數(shù)。這個構(gòu)造函數(shù)稱為默認構(gòu)造函數(shù)。來看一個例子;
public class ReLearnConstructor { String languages; int a; boolean b; float c; public static void main(String[] args) { ReLearnConstructor rc = new ReLearnConstructor(); System.out.println("默認值:"); System.out.println("languages:" + rc.languages); System.out.println("a:" + rc.a); System.out.println("b:" + rc.b); System.out.println("c:" + rc.c); } }
?
運行結(jié)果:
?
默認值: languages:null a:0 b:false c:0.0可以看到,我們還沒有創(chuàng)建任何構(gòu)造函數(shù)。因此,Java 編譯器會自動創(chuàng)建默認構(gòu)造函數(shù)。上述表格得以印證。
?
原生方法和構(gòu)造器的區(qū)別
構(gòu)造函數(shù)必須與在 Java 中定義的類具有相同的名稱
當(dāng)方法沒有返回任何值時,構(gòu)造函數(shù)不會返回任何類型,而方法則具有返回類型或 void
在對象創(chuàng)建時,僅調(diào)用構(gòu)造函數(shù)一次,而方法可以被調(diào)用任何次數(shù)
如果我們不用構(gòu)造器來給屬性賦值的話,可以先使用 new 運算符獲取類的實例,并使用類的 setter 方法設(shè)置值,如下:
import java.util.Arrays; class Person { private String name; private int age; @Override public String toString() { return Arrays.asList(name, String.valueOf(age)).toString(); } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } // getters } // Initialize an object in Java class Main { public static void main(String[] args) { Person person = new Person(); person.setName("Yuzhou1su"); person.setAge(22); System.out.println(person); } }
?
通過構(gòu)造器進行初始化就可以省去我們的 setter 方法。
如下的例子:
?
import java.util.Arrays; class Person { private String name; private int age; // 構(gòu)造器 public Person(String name, int age) { this.name = name; this.age = age; } public String toString() { return Arrays.asList(name, String.valueOf(age)).toString(); } } class SimpleConstructor { public static void main(String[] args) { Person person = new Person("Yuzhou1su", 22); System.out.println(person); } }
?
運行結(jié)果:
?
[Yuzhou1su, 22]
?
構(gòu)造器重載
與 Java 方法重載類似,我們也可以創(chuàng)建兩個或多個具有不同參數(shù)的構(gòu)造函數(shù)。這稱為構(gòu)造函數(shù)重載。
public class ReLearnConstructor { String language; public ReLearnConstructor() { this.language = "Java"; } // 構(gòu)造器 public ReLearnConstructor(String language) { this.language = language; } public void getName() { System.out.println("編程語言:" + this.language); } public static void main(String[] args) { ReLearnConstructor rc1 = new ReLearnConstructor(); ReLearnConstructor rc2 = new ReLearnConstructor("Python"); rc1.getName(); rc2.getName(); } }
?
在上面的例子中,我們有兩個構(gòu)造函數(shù):ReLearnConstructor () 和 ReLearnConstructor (String language)。在這里,兩個構(gòu)造函數(shù)都用不同的值初始化變量語言的值。根據(jù)創(chuàng)建對象時傳遞的參數(shù),調(diào)用不同的構(gòu)造函數(shù),分配不同的值。
運行結(jié)果:
編程語言:Java 編程語言:Python
?
拷貝構(gòu)造器
Java 中的拷貝構(gòu)造方法是一種使用該類的一個對象構(gòu)造另外一個對象的構(gòu)造方法。 復(fù)制構(gòu)造函數(shù)是一種特殊構(gòu)造函數(shù),用于將新對象創(chuàng)建為現(xiàn)有對象的副本。它只需要一個參數(shù),它將是同一類的另一個實例。我們可以使用 this () 語句從復(fù)制構(gòu)造函數(shù)中顯式調(diào)用另一個構(gòu)造函數(shù):
public class ReLearnConstructor { private String language; // 構(gòu)造器 public ReLearnConstructor(String language) { this.language = language; } // 拷貝構(gòu)造器 public ReLearnConstructor(ReLearnConstructor rc) { this.language = rc.language; } public void getName() { System.out.println("編程語言:" + this.language); } public static void main(String[] args) { ReLearnConstructor rc = new ReLearnConstructor("Python"); ReLearnConstructor copyOfrc = new ReLearnConstructor(rc); rc.getName(); copyOfrc.getName(); } }
?
運行結(jié)果:
?
編程語言:Python 編程語言:Python
?
當(dāng)需要拷貝一個帶有多個成員變量的復(fù)雜對象或者想構(gòu)造已存在對象的深拷貝對象時非常有用。
匿名內(nèi)部類
除了上文介紹的使用構(gòu)造器的方法,另一種初始化對象的方法是使用 “雙大括號初始化”。這將創(chuàng)建一個匿名內(nèi)部類,其中只有一個實例初始化程序。建議不要使用這種方法。
import java.util.Arrays; class Person { private String name; private int age; @Override public String toString() { return Arrays.asList(name, String.valueOf(age)).toString(); } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } // getters } // Initialize an object in Java class Main { public static void main(String[] args) { // Anonymous class Person person = new Person() {{ // Initializer block setName("Yuzhou1su"); setAge(22); }}; System.out.println(person); } }
?
總結(jié)
實例化對象時會隱式調(diào)用構(gòu)造函數(shù)。
創(chuàng)建構(gòu)造函數(shù)的兩條規(guī)則是:構(gòu)造函數(shù)的名稱應(yīng)與類相同。Java 構(gòu)造函數(shù)不能有返回類型。
如果一個類沒有構(gòu)造函數(shù),Java 編譯器會在運行時自動創(chuàng)建一個默認構(gòu)造函數(shù)。默認構(gòu)造函數(shù)使用默認值初始化實例變量。例如 int 變量將被初始化為 0
構(gòu)造函數(shù)類型:
無參構(gòu)造器 - 不接受任何參數(shù)的構(gòu)造函數(shù)參數(shù)化構(gòu)造函數(shù)
接受參數(shù)的構(gòu)造器 - 接受參數(shù)的構(gòu)造函數(shù)
默認構(gòu)造器 - 如果沒有明確定義,Java 編譯器會自動創(chuàng)建一個構(gòu)造函數(shù)。
構(gòu)造函數(shù)不能被 abstract、static 或 final 修飾
編譯器會報如下錯誤:
Illegal modifier for the constructor in type ReLearnConstructor; only public, protected & private are permitted
?
構(gòu)造函數(shù)可以重載但不能被覆蓋
審核編輯:湯梓紅
評論
查看更多