java 构造器(constructor)是什么
構(gòu)造器是什么?
構(gòu)造器就是和類名相同但無(wú)返回類型的方法。用于當(dāng)前或某一對(duì)象的實(shí)例化,并將當(dāng)前或某一對(duì)象返回。要得到一個(gè)類的實(shí)例時(shí),往往是要運(yùn)行其構(gòu)造函數(shù)的。
使用構(gòu)造器時(shí)需要記住:
1.構(gòu)造器必須與類同名(如果一個(gè)源文件中有多個(gè)類,那么構(gòu)造器必須與公共類同名)
2.每個(gè)類可以有一個(gè)以上的構(gòu)造器
3.構(gòu)造器可以有0個(gè)、1個(gè)或1個(gè)以上的參數(shù)
4.構(gòu)造器沒有返回值
5.構(gòu)造器總是伴隨著new操作一起調(diào)用
6.不添加任何構(gòu)造器會(huì)默認(rèn)有空的構(gòu)造器
繼承與構(gòu)造器
使用super調(diào)用父類構(gòu)造器的語(yǔ)句必須是子類構(gòu)造器的第一條語(yǔ)句
為什么加上super?
Java的構(gòu)造器并不是函數(shù),所以他并不能被繼承,這在我們extends的時(shí)候?qū)懽宇惖臉?gòu)造器時(shí)比較的常見,即使子類構(gòu)造器參數(shù)和父類的完全一樣,我們也要寫super就是因?yàn)檫@個(gè)原因。
如果子類構(gòu)造器沒有顯式地調(diào)用父類的構(gòu)造器,則將自動(dòng)調(diào)用父類的默認(rèn)(沒有參數(shù))的構(gòu)造器。如果父類沒有不帶參數(shù)的構(gòu)造器,并且在子類的構(gòu)造器中又沒有顯式地調(diào)用父類的構(gòu)造器,則java編譯器將報(bào)告錯(cuò)誤
構(gòu)造方法和實(shí)例方法的區(qū)別:一、主要的區(qū)別在于三個(gè)方面:修飾符、返回值、命名1、和實(shí)例方法一樣,構(gòu)造器可以有任何訪問(wèn)的修飾符,public、private、protected或者沒有修飾符 ,都可以對(duì)構(gòu)造方法進(jìn)行修飾。不同于實(shí)例方法的是構(gòu)造方法不能有任何非訪問(wèn)性質(zhì)的修飾符修飾,例如static、final、synchronized、abstract等都不能修飾構(gòu)造方法。解釋:構(gòu)造方法用于初始化一個(gè)實(shí)例對(duì)象,所以static修飾是沒有任何意義的;多個(gè)線程不會(huì)同時(shí)創(chuàng)建內(nèi)存地址相同的同一個(gè)對(duì)象,所以synchronized修飾沒有意義;構(gòu)造方法不能被子類繼承,所以final和abstract修飾沒有意義。2、返回類型是非常重要的,實(shí)例方法可以返回任何類型的值或者是無(wú)返回值(void),而構(gòu)造方法是沒有返回類型的,void也不行。3、至于命名就是構(gòu)造方法與類名相同,當(dāng)然了實(shí)例方法也可以與類名相同,但是習(xí)慣上我們?yōu)閷?shí)例方法命名的時(shí)候通常是小寫的,另一方面也是與構(gòu)造方法區(qū)分開。而構(gòu)造方法與類名相同,所以首字母一般大寫。下面看幾個(gè)例子熟悉一下:public class Sample { private int x; public Sample() { // 不帶參數(shù)的構(gòu)造方法 this(1); } public Sample(int x) { //帶參數(shù)的構(gòu)造方法 this.x=x; } public int Sample(int x) { //不是構(gòu)造方法 return x++; } } 上面的例子即使不通過(guò)注釋我們也很容易能區(qū)分開的,再看下面一個(gè)例子public class Mystery { private String s; public void Mystery() { //不是構(gòu)造方法 s = "constructor"; } void go() { System.out.println(s); } public static void main(String[] args) { Mystery m = new Mystery(); m.go(); } } 程序執(zhí)行的結(jié)果為null,雖然說(shuō)Mystery m = new Mystery();調(diào)用了Mystery 類的構(gòu)造方法,但是public void Mystery()并不是構(gòu)造方法,他只是一個(gè)普通的實(shí)例方法而已,那該類的構(gòu)造方法哪去了呢?二、說(shuō)到這就得說(shuō)一下java的默認(rèn)構(gòu)造方法我們知道,java語(yǔ)言中規(guī)定每個(gè)類至少要有一個(gè)構(gòu)造方法,為了保證這一點(diǎn),當(dāng)用戶沒有給java類定義明確的構(gòu)造方法的時(shí)候,java為我們提供了一個(gè)默認(rèn)的構(gòu)造方法,這個(gè)構(gòu)造方法沒有參數(shù),修飾符是public并且方法體為空。其實(shí)默認(rèn)的構(gòu)造方法還分為兩種,一種就是剛剛說(shuō)過(guò)的隱藏的構(gòu)造方法,另一種就是顯示定義的默認(rèn)構(gòu)造方法.如果一個(gè)類中定義了一個(gè)或者多個(gè)構(gòu)造方法,并且每一個(gè)構(gòu)造方法都是帶有參數(shù)形式的,那么這個(gè)類就沒有默認(rèn)的構(gòu)造方法,看下面的例子。public class Sample1{} public class Sample2{ public Sample2(int a){System.out.println("My Constructor");} } public class Sample3{ public Sample3(){System.out.println("My Default Constructor");} } 上面的三個(gè)類中Sample1有一個(gè)隱式的默認(rèn)構(gòu)造方法,下列語(yǔ)句Sample1 s1=new Sample()合法;Sample2沒有默認(rèn)的構(gòu)造方法,下列語(yǔ)句Sample2 s2=new Sample2()不合法,執(zhí)行會(huì)編譯錯(cuò)誤Sample3有一個(gè)顯示的默認(rèn)構(gòu)造方法,所以以下語(yǔ)句Sample3 s3=new Sample3();合法。三、實(shí)例方法和構(gòu)造方法中this、super的使用."this"的用法實(shí)例方法中可以使用this關(guān)鍵字,它指向正在執(zhí)行方法的類的實(shí)例對(duì)象,當(dāng)然static方法中是不可以使用this對(duì)象的,因?yàn)殪o態(tài)方法不屬于類的實(shí)例對(duì)象;而構(gòu)造方法中同樣可以使用this關(guān)鍵字,構(gòu)造器中的this是指向同一個(gè)對(duì)象中不同參數(shù)的另一個(gè)構(gòu)造器。讓我們來(lái)看下面的一段代碼:public class Platypus { String name; Platypus(String input) { name = input; } Platypus() { this("John/Mary Doe"); } public static void main(String args[]) { Platypus p1 = new Platypus("digger"); Platypus p2 = new Platypus(); System.out.println(p1.name + "----" + p2.name); } } 上面的代碼中 類有兩個(gè)構(gòu)造器,第一個(gè)構(gòu)造器給類的成員name賦值,第二個(gè)構(gòu)造器調(diào)用第一個(gè)構(gòu)造器給類的成員name一個(gè)初始值Jonn/Mary Doe所以程序執(zhí)行結(jié)果:digger----John/Mary Doe需要注意的兩個(gè)地方是:1、構(gòu)造方法中通過(guò)this關(guān)鍵字調(diào)用其他構(gòu)造方法時(shí),那么這句代碼必須放在第一行,否則會(huì)編譯錯(cuò)誤。2、構(gòu)造方法中只能通過(guò)this調(diào)用一次其他的構(gòu)造方法。 "super"的用法:實(shí)例方法和構(gòu)造方法中的super關(guān)鍵字都用于去指向父類,實(shí)例方法中的super關(guān)鍵字是去調(diào)用父類當(dāng)中的某個(gè)方法,看下面的代碼:class getBirthInfo { void getBirthInfo() { System.out.println("born alive."); } } class Platypus1 extends getBirthInfo { void getBirthInfo() { System.out.println("hatch from eggs"); System.out.println("a mammal normally is "); super.getBirthInfo(); } } public class test1 { public static void main(String[] args) { Platypus1 p1=new Platypus1(); p1.getBirthInfo(); } } 上面的例子使用super.getBirthInfo();調(diào)用了它的父類的void getBirthInfo()方法。構(gòu)造器中使用super關(guān)鍵字調(diào)用父類中的構(gòu)造器,看下面的代碼:class getBirthInfo { getBirthInfo(){ System.out.println("auto"); } void aa() { System.out.println("born alive."); } } class Platypus1 extends getBirthInfo { Platypus1() { super(); System.out.println("hatch from eggs"); System.out.println("a mammal normally is "); } } public class test1 { public static void main(String[] args) { Platypus1 p1=new Platypus1(); } } 執(zhí)行了代碼我們就會(huì)看到構(gòu)造器中的super調(diào)用了父類的構(gòu)造方法。 類的繼承機(jī)制使得子類可以調(diào)用父類的功能,下面介紹類在繼承關(guān)系的初始化順序問(wèn)題 請(qǐng)看實(shí)例1:class SuperClass { SuperClass() { System.out.println("SuperClass constructor"); } } public class SubClass extends SuperClass { SubClass() { System.out.println("SubClass constructor"); } public static void main(String[] args) { SubClass sub = new SubClass(); } } 執(zhí)行結(jié)果:SuperClass constructorSubClass constructor代碼中我們只實(shí)例化子類一個(gè)對(duì)象,但從執(zhí)行結(jié)果上看程序一開始并不是運(yùn)行子類的構(gòu)造方法,而是先執(zhí)行父類的默認(rèn)構(gòu)造方法,然后再執(zhí)行子類的構(gòu)造方法.所以我們?cè)趯?shí)例化子類對(duì)象時(shí),程序會(huì)先調(diào)用父類的默認(rèn)構(gòu)造方法,然后再執(zhí)行子類的構(gòu)造方法。 再看實(shí)例2:class SuperClass { SuperClass(String str) { System.out.println("Super with a string."); } } public class SubClass extends SuperClass { SubClass(String str) { System.out.println("Sub with a string."); } public static void main(String[] args) { SubClass sub = new SubClass("sub"); } } 此程序在JDK下不能編譯成功,因?yàn)槲覀冊(cè)趯?shí)例化子類對(duì)象的時(shí)候會(huì)先調(diào)用其父類默認(rèn)的構(gòu)造方法,但是它的父類沒有默認(rèn)的構(gòu)造方法,所以不能編譯成功。解決辦法:1、在父類中加一個(gè)顯示的默認(rèn)構(gòu)造方法2、在子類的構(gòu)造方法中加一句super(str)并且必須在構(gòu)造器的第一句。兩個(gè)辦法都可以解決程序編譯的問(wèn)題,但是執(zhí)行結(jié)果是不一樣的.第一種執(zhí)行結(jié)果為:Sub with a string.第二種執(zhí)行結(jié)果為:Super with a string. Sub with a string. 第二種方法即使父類中有顯示的默認(rèn)構(gòu)造方法也不會(huì)被調(diào)用。 再看實(shí)例三:class One { One(String str) { System.out.println(str); } } class Two { One one_1 = new One("one-1"); One one_2 = new One("one-2"); One one_3 = new One("one-3"); Two(String str) { System.out.println(str); } } public class Test { public static void main(String[] args) { System.out.println("Test main() start"); Two two = new Two("two"); } } 執(zhí)行結(jié)果:Test main() startone-1one-2one-3two我們?cè)趍ain方法中實(shí)例了一個(gè)Two的對(duì)象,但是程序在實(shí)例Two對(duì)象時(shí)并沒有先調(diào)用Two的構(gòu)造方法,而是先初始化Two類的成員變量,Two類中有三個(gè)成員變量,他們都是One類的對(duì)象,所以要依次執(zhí)行One類的構(gòu)造方法,然后再初始化Two類的對(duì)象。既在實(shí)例化類的對(duì)象時(shí),類中的成員變量會(huì)首先進(jìn)行初始化,如果其中的成員變量有對(duì)象,那么它們也會(huì)按照順序執(zhí)行初始化工作。在所有類成員初始化完成后,才調(diào)用對(duì)象所在類的構(gòu)造方法創(chuàng)建對(duì)象。構(gòu)造方法作用就是初始化。 再看實(shí)例四:class One { One(String str) { System.out.println(str); } } class Two { One one_1 = new One("one-1"); One one_2 = new One("one-2"); static One one_3 = new One("one-3"); Two(String str) { System.out.println(str); } } public class Test { public static void main(String[] args) { System.out.println("Test main() start"); Two two_1 = new Two("two-1"); System.out.println("------------"); Two two_2 = new Two("two-2"); } } 執(zhí)行結(jié)果:Test main() startone-3one-1one-2two-1------------one-1one-2two-2結(jié)論:如果一個(gè)類中有靜態(tài)對(duì)象,那么他會(huì)在非靜態(tài)對(duì)象初始化前進(jìn)行初始化,但只初始化一次。而非靜態(tài)對(duì)象每次調(diào)用時(shí)都要初始化。 再看實(shí)例五:class One { One(String str) { System.out.println(str); } } class Two { One one_1 = new One("one-1"); One one_2 = new One("one-2"); static One one_3 = new One("one-3"); Two(String str) { System.out.println(str); } } public class Test { static Two two_3 = new Two("two-3"); public static void main(String[] args) { System.out.println("Test main() start"); Two two_1 = new Two("two-1"); System.out.println("------------"); Two two_2 = new Two("two-2"); } } 執(zhí)行結(jié)果:one-3one-1one-2two-3Test main() startone-1one-2two-1------------one-1one-2two-2結(jié)論:程序中主類的靜態(tài)變量會(huì)在main()方法執(zhí)行前初始化。結(jié)果中只輸出了一次one-3,這也說(shuō)明:如果一個(gè)類中有靜態(tài)對(duì)象,那么它會(huì)在非靜態(tài)對(duì)象前初始化,但只初始化一次。非靜態(tài)對(duì)象每次調(diào)用時(shí)都要初始化。 總結(jié)初始化順序:1.主類的靜態(tài)成員首先初始化。 2.主類的父類的構(gòu)造方法被調(diào)用。 3.主類的非靜態(tài)對(duì)象(變量)初始化。 4.調(diào)用主類的構(gòu)造方法。轉(zhuǎn)載:
https://blog.csdn.net/qq_41620160/article/details/79443524
總結(jié)
以上是生活随笔為你收集整理的java 构造器(constructor)是什么的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ubuntu搭建esp-idf开发环境
- 下一篇: 温州市工程师职称申报专业