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