1. 程式人生 > >Java中的構造方法總結

Java中的構造方法總結

構造方法和例項方法的區別

一、主要的區別在於三個方面:修飾符、返回值、命名

1、和例項方法一樣,構造器可以有任何訪問的修飾符,public、private、protected或者沒有修飾符   ,都可以對構造方法進行修飾。不同於例項方法的是構造方法不能有任何非訪問性質的修飾符修飾,例如static、final、synchronized、abstract等都不能修飾構造方法 解釋:構造方法用於初始化一個例項物件,所以static修飾是沒有任何意義的;多個執行緒不會同時建立記憶體地址相同的同一個物件,所以synchronized修飾沒有意義; 構造方法不能被子類繼承,所以final和abstract修飾沒有意義。
2、返回型別是非常重要的,例項方法可以返回任何型別的值或者是無返回值(void),而構造方法是沒有返回型別的,void也不行。 3、至於命名就是構造方法與類名相同,當然了例項方法也可以與類名相同,但是習慣上我們為例項方法命名的時候通常是小寫的,另一方面也是與構造方法區分開。 而構造方法與類名相同,所以首字母一般大寫。 下面看幾個例子熟悉一下:
  1. publicclass Sample {  
  2.     privateint x;  
  3.     public Sample() { // 不帶引數的構造方法
  4.         this(1);  
  5.     }  
  6.     public Sample(int
     x) { //帶引數的構造方法
  7.         this.x=x;  
  8.     }  
  9.     publicint Sample(int x) { //不是構造方法
  10.         return x++;  
  11.     }  
  12. }  
上面的例子即使不通過註釋我們也很容易能區分開的,再看下面一個例子
  1. publicclass Mystery {  
  2.     private String s;  
  3.     publicvoid Mystery() { //不是構造方法
  4.     s = "constructor";  
  5.     }  
  6.     void go() {  
  7.     System.out.println(s);  
  8.     }  
  9.     publicstaticvoid main(String[] args) {  
  10.     Mystery m = new Mystery();  
  11.     m.go();  
  12.     }  
  13. }  
程式執行的結果為null,雖然說Mystery m = new Mystery();呼叫了Mystery 類的構造方法,但是public void Mystery()並不是構造方法,他只是一個普通的例項方法而已,那該類的構造方法哪去了呢? 二、說到這就得說一下java的預設構造方法 我們知道,java語言中規定每個類至少要有一個構造方法,為了保證這一點,當用戶沒有給java類定義明確的構造方法的時候,java為我們提供了一個預設的構造方法,這個構造方法沒有引數,修飾符是public並且方法體為空。如果使用者有定義構造方法,就不會有預設構造方法!!! 其實預設的構造方法還分為兩種,一種就是剛剛說過的隱藏的構造方法,另一種就是顯示定義的預設構造方法. 如果一個類中定義了一個或者多個構造方法,並且每一個構造方法都是帶有引數形式的,那麼這個類就沒有預設的構造方法,看下面的例子。
  1. public class Sample1{}  
  2. public class Sample2{  
  3.     public Sample2(int a){System.out.println("My Constructor");}  
  4. }  
  5. public class Sample3{  
  6.     public Sample3(){System.out.println("My Default Constructor");}  
  7. }  
上面的三個類中Sample1有一個隱式的預設構造方法,下列語句Sample1 s1=new Sample()合法; Sample2沒有預設的構造方法,下列語句Sample2 s2=new Sample2()不合法,執行會編譯錯誤 Sample3有一個顯示的預設構造方法,所以以下語句Sample3  s3=new Sample3();合法。

三、例項方法和構造方法中this、super的使用. "this"的用法 例項方法中可以使用this關鍵字,它指向正在執行方法的類的例項物件,當然static方法中是不可以使用this物件的,因為靜態方法不屬於類的例項物件;而構造方法中同樣可以使用this關鍵字,構造器中的this是指向同一個物件中不同引數的另一個構造器。讓我們來看下面的一段程式碼:
  1. publicclass Platypus {  
  2.     String name;  
  3.     Platypus(String input) {  
  4.         name = input;  
  5.     }  
  6.     Platypus() {  
  7.         this("John/Mary Doe");  
  8.     }  
  9.     publicstaticvoid main(String args[]) {  
  10.         Platypus p1 = new Platypus("digger");  
  11.         Platypus p2 = new Platypus();  
  12.         System.out.println(p1.name + "----" + p2.name);  
  13.     }  
  14. }  
上面的程式碼中 類有兩個構造器,第一個構造器給類的成員name賦值,第二個構造器呼叫第一個構造器給類的成員name一個初始值Jonn/Mary Doe 所以程式執行結果:digger----John/Mary Doe
需要注意的兩個地方是:
1、構造方法中通過this關鍵字呼叫其他構造方法時,那麼這句程式碼必須放在第一行,否則會編譯錯誤。 2、構造方法中只能通過this呼叫一次其他的構造方法。 "super"的用法: 例項方法和構造方法中的super關鍵字都用於去指向父類,例項方法中的super關鍵字是去呼叫父類當中的某個方法,看下面的程式碼:
  1. class getBirthInfo {  
  2.     void getBirthInfo() {  
  3.         System.out.println("born alive.");  
  4.     }  
  5. }  
  6. class Platypus1 extends getBirthInfo  
  7. {  
  8.     void getBirthInfo() {  
  9.            System.out.println("hatch from eggs");  
  10.            System.out.println("a mammal normally is ");  
  11.            super.getBirthInfo();  
  12.       }  
  13. }  
  14. public class test1 {  
  15.     public static void main(String[] args) {  
  16.         Platypus1 p1=new Platypus1();  
  17.         p1.getBirthInfo();  
  18.     }  
  19. }  
上面的例子使用super.getBirthInfo();呼叫了它的父類的void getBirthInfo()方法。 構造器中使用super關鍵字呼叫父類中的構造器,看下面的程式碼:
  1. class getBirthInfo {  
  2.     getBirthInfo(){  
  3.         System.out.println("auto");  
  4.     }  
  5.     void aa() {  
  6.         System.out.println("born alive.");  
  7.     }  
  8. }  
  9. class Platypus1 extends getBirthInfo  
  10. {  
  11.       Platypus1() {  
  12.         super();  
  13.         System.out.println("hatch from eggs");  
  14.         System.out.println("a mammal normally is ");  
  15.       }  
  16. }  
  17. publicclass test1 {  
  18.     publicstaticvoid main(String[] args) {  
  19.         Platypus1 p1=new Platypus1();  
  20.     }  
  21. }  
執行了程式碼我們就會看到構造器中的super呼叫了父類的構造方法。

類的繼承機制使得子類可以呼叫父類的功能,下面介紹類在繼承關係的初始化順序問題 請看例項1:
  1. class SuperClass   
  2. {   
  3.     SuperClass()   
  4.     {   
  5.         System.out.println("SuperClass constructor");   
  6.     }   
  7. }   
  8. publicclass SubClass extends SuperClass {  
  9.     SubClass()   
  10.     {   
  11.         System.out.println("SubClass constructor");   
  12.     }   
  13.     publicstaticvoid main(String[] args) {  
  14.         SubClass sub = new SubClass();   
  15.     }   
  16. }   
執行結果:SuperClass constructor
     SubClass constructor 程式碼中我們只例項化子類一個物件,但從執行結果上看程式一開始並不是執行子類的構造方法,而是先執行父類的預設構造方法,然後再執行子類的構造方法.所以我們在例項化子類物件時,程式會先呼叫父類的預設構造方法,然後再執行子類的構造方法。 再看例項2:
  1. class SuperClass   
  2. {   
  3.     SuperClass(String str)   
  4.     {   
  5.     System.out.println("Super with a string.");   
  6.     }   
  7. }   
  8. publicclass SubClass extends SuperClass   
  9. {   
  10.     SubClass(String str)   
  11.     {   
  12.     System.out.println("Sub with a string.");   
  13.     }   
  14.     publicstaticvoid main(String[] args)   
  15.     {   
  16.     SubClass sub = new SubClass("sub");   
  17.     }   
  18. }   
注意:此程式在JDK下不能編譯成功,因為我們在例項化子類物件的時候會先呼叫其父類預設的構造方法(除非例項化物件的建構函式中有呼叫任意的父類構造方法),但是它的父類沒有預設的構造方法,所以不能編譯成功。易錯地方!! 解決辦法: 1、在父類中加一個顯示的預設構造方法 2、在子類的構造方法中加一句super(str)並且必須在構造器的第一句。 兩個辦法都可以解決程式編譯的問題,但是執行結果是不一樣的. 第一種執行結果為:Sub with a string. 第二種執行結果為:Super with a string. 
                       Sub with a string.     第二種方法即使父類中有顯示的預設構造方法也不會被呼叫。
再看例項三:
  1. class One   
  2. {   
  3.     One(String str)   
  4.     {   
  5.     System.out.println(str);   
  6.     }   
  7. }   
  8. class Two   
  9. {   
  10.     One one_1 = new One("one-1");   
  11.     One one_2 = new One("one-2");   
  12.     One one_3 = new One("one-3");   
  13.     Two(String str)   
  14.     {   
  15.     System.out.println(str);   
  16.     }   
  17. }   
  18. publicclass Test   
  19. {   
  20.     publicstaticvoid main(String[] args)   
  21.     {   
  22.     System.out.println("Test main() start");   
  23.     Two two = new Two("two");   
  24.     }   
  25. }  
執行結果: Test main() start
one-1
one-2
one-3
two 我們在main方法中例項了一個Two的物件,但是程式在例項Two物件時並沒有先呼叫Two的構造方法,而是先初始化Two類的成員變數,Two類中有三個成員變數,他們都是One類的物件,所以要依次執行One類的構造方法,然後再初始化Two類的物件。 在例項化類的物件時,類中的成員變數會首先進行初始化,如果其中的成員變數有物件,那麼它們也會按照順序執行初始化工作。在所有類成員初始化完成後,才呼叫物件所在類的構造方法建立物件。構造方法作用就是初始化。  再看例項四:
  1. class One   
  2.     {   
  3.     One(String str)   
  4.     {   
  5.     System.out.println(str);   
  6.     }   
  7. }   
  8. class Two   
  9. {   
  10.     One one_1 = new One("one-1");   
  11.     One one_2 = new One("one-2");   
  12.     static One one_3 = new One("one-3");   
  13.     Two(String str)   
  14.     {   
  15.     System.out.println(str);   
  16.     }   
  17. }   
  18. publicclass Test   
  19. {   
  20.     publicstatic<