Java 面向對象編程之構造方法、構造代碼塊html
面向對象編程是咱們認識世界,創造事物的一種新的思惟,其實就抓大放小,將全部共性的事物進行封裝的過程。編程人員在進行流程做業時,能夠方便的進行復用。java
站在面向對象的角度看問題,編程就是對象的動做的調用;站在面向過程的角度,編程就是動做的執行者。「把大象裝進冰箱」就能夠完美的解釋面向對象和麪向過程的區別。編程
就如同一個 「Baby」 對象創建以後,那麼生孩子的過程就會變得很簡單:安全
public class Baby { // 定義一個Baby類 Long IDcard; String name; public void eat() { System.out.println(name+"...eat..."); } public void run(){ System.out.println(name+"...run..."); } }
但是不是全部生下來的孩子都是同樣的,他們具備不一樣的身份證號碼,不一樣的名字。jvm
因此,new一個對象很簡單,可是要考慮初始化對象,並給予不一樣的區別就要對這個類進行構造方法。函數
構造方法(構造函數):給對象進行統一的初始化。如代碼:測試
public class Baby { Long IDcard; String name; public void eat() { System.out.println(name+"...eat..."); } public void run(){ System.out.println(name+"...run..."); } public Baby() // 無參數的構造函數 { System.out.println("my name is "+name+";my idcard is :"+IDcard); } public Baby(Long IDcard,String name) // 有參數的構造函數 { System.out.println("my name is "+name+";my idcard is :"+IDcard); } }
1. 構造函數是沒有返回值類型的。
2. 構造函數的函數名必需要與類名一致。
3. 構造函數並非由咱們手動調用的,而是在建立對應的對象時,jvm就會主動調用到對應的構造函數。
4. 若是一個類沒有顯式的寫上一個構造方法時,那麼java編譯器會爲該類添加一個無參的構造函數的。
5. 若是一個類已經顯式的寫上一個構造方法時,那麼java編譯器則不會再爲該類添加 一個無參的構造方法。
6. 構造函數是能夠在一個類中以函數重載的形式存在多個的。spa
1. 返回值類型的區別:htm
2. 函數名的區別:對象
3. 調用方式的區別:
4. 做用上的區別:
在Java中,靜態代碼塊、構造代碼塊、構造函數、普通代碼塊的執行順序是一個筆試的考點,經過這篇文章但願能完全瞭解它們之間的執行順序。
(1)靜態代碼塊:
代碼結構:在java類中使用static關鍵字和{}聲明的代碼塊,通常是類中才有這樣的結構,方法中不存在。
public class CodeBlock { static{ System.out.println("靜態代碼塊"); } }
執行時機:靜態代碼塊在類被加載的時候就運行了,並且只運行一次,而且優先於各類代碼塊以及構造函數。若是一個類中有多個靜態代碼塊,會按照書寫順序依次執行。後面在比較的時候會經過具體實例來證實。
靜態代碼塊的做用:通常狀況下,若是有些代碼須要在項目啓動的時候就執行,這時候就須要靜態代碼塊。好比一個項目啓動須要加載的不少配置文件等資源,咱們就能夠都放入靜態代碼塊中。
靜態代碼塊不能存在任何方法體中:
靜態代碼塊是在類加載的時候就要運行了。咱們分狀況討論:
對於普通方法,因爲普通方法是經過加載類,而後new出實例化對象,經過對象才能運行這個方法,而靜態代碼塊只須要加載類以後就能運行了。
對於靜態方法,在類加載的時候,靜態方法也已經加載了,可是咱們必需要經過類名或者對象名才能訪問,也就是說相比於靜態代碼塊,靜態代碼塊是主動運行的,而靜態方法是被動運行的。
不論是哪一種方法,咱們須要明確靜態代碼塊的存在在類加載的時候就自動運行了,而放在不論是普通方法仍是靜態方法中,都是不能自動運行的。
靜態代碼塊不能訪問普通變量:普通變量只能經過對象來調用,是不能放在靜態代碼塊中的。
(2)構造代碼塊:
代碼結構:在java類中使用{}聲明的代碼塊(和靜態代碼塊的區別是少了static關鍵字):
public class CodeBlock { static{ System.out.println("靜態代碼塊"); } { System.out.println("構造代碼塊"); } }
執行時機:構造代碼塊在建立對象時被調用,每次建立對象都會調用一次,可是優先於構造函數執行。須要注意的是,聽名字咱們就知道,構造代碼塊不是優先於構造函數執行,而是依託於構造函數,也就是說,若是你不實例化對象,構造代碼塊是不會執行的。怎麼理解呢?咱們看看下面這段代碼:
public class CodeBlock { { System.out.println("構造代碼塊"); } public CodeBlock(){ System.out.println("無參構造函數"); } public CodeBlock(String str){ System.out.println("有參構造函數"); } }
若是存在多個構造代碼塊,則執行順序按照書寫順序依次執行。
構造代碼塊的做用:
和構造函數的做用相似,都能對對象進行初始化,而且只要建立一個對象,構造代碼塊都會執行一次。可是反過來,構造函數則不必定每一個對象創建時都執行(多個構造函數狀況下,創建對象時傳入的參數不一樣則初始化使用對應的構造函數)。
利用每次建立對象的時候都會提早調用一次構造代碼塊特性,咱們能夠作諸如統計建立對象的次數等功能。
(3)構造函數:
1.構造函數的命名必須和類名徹底相同。在java中普通函數能夠和構造函數同名,可是必須帶有返回值;
2.構造函數的功能主要用於在類的對象建立時定義初始化的狀態。它沒有返回值,也不能用void來修飾。這就保證了它不只什麼也不用自動返回,並且根本不能有任何選擇。而其餘方法都有返回值,即便是void返回值。儘管方法體自己不會自動返回什麼,但仍然可讓它返回一些東西,而這些東西多是不安全的;
3.構造函數不能被直接調用,必須經過new運算符在建立對象時纔會自動調用;而通常的方法是在程序執行到它的時候被調用的;
4.當定義一個類的時候,一般狀況下都會顯示該類的構造函數,並在函數中指定初始化的工做也可省略,不過Java編譯器會提供一個默認的構造函數.此默認構造函數是不帶參數的。而通常的方法不存在這一特色;
(4)普函數:
普通代碼塊和構造代碼塊的區別是,構造代碼塊是在類中定義的,而普通代碼塊是在方法體中定義的。且普通代碼塊的執行順序和書寫順序一致。
public void sayHello(){ { System.out.println("普通代碼塊"); } }
(5)執行順序:
靜態代碼塊>構造代碼塊>構造函數>普通代碼塊
public class CodeBlock { static{ System.out.println("靜態代碼塊"); } { System.out.println("構造代碼塊"); } public CodeBlock(){ System.out.println("無參構造函數"); } public void sayHello(){ { System.out.println("普通代碼塊"); } } public static void main(String[] args) { System.out.println("執行了main方法"); new CodeBlock().sayHello();; System.out.println("---------------"); new CodeBlock().sayHello();; } }
(6)父類和子類的執行順序:
對象的初始化順序:
首先執行父類靜態的內容,父類靜態的內容執行完畢後,接着去執行子類的靜態的內容,當子類的靜態內容執行完畢以後,再去看父類有沒有構造代碼塊,若是有就執行父類的構造代碼塊,父類的構造代碼塊執行完畢,接着執行父類的構造方法;父類的構造方法執行完畢以後,它接着去看子類有沒有構造代碼塊,若是有就執行子類的構造代碼塊。子類的構造代碼塊執行完畢再去執行子類的構造方法。
總之一句話,靜態代碼塊內容先執行,接着執行父類構造代碼塊和構造方法,而後執行子類構造代碼塊和構造方法。
父類:SuperClass.java
public class SuperClass { static{ System.out.println("父類靜態代碼塊"); } { System.out.println("父類構造代碼塊"); } public SuperClass(){ System.out.println("父類構造函數"); } }
子類:SubClass.java
public class SubClass extends SuperClass{ static{ System.out.println("子類靜態代碼塊"); } { System.out.println("子類構造代碼塊"); } public SubClass(){ System.out.println("子類構造函數"); } }
測試:
public static void main(String[] args) { SubClass sb = new SubClass(); System.out.println("------------"); SubClass sb1 = new SubClass(); }