本篇博文主要是爲新手、對java語言感興趣的人和那些沒有系統學習過java基礎知識的人進行一個總結,在文章中對構造函數進行了較爲詳細的說明和討論,也包含了我我的對於java面向對象中構造函數的一些見解。但願走在java學習道路上的同行者能夠有一個較爲清晰的認知和理解。固然僅爲我的觀點,水平有限,不足之處,還請你們多多指出,互相交流學習。java
1.構造函數的概念編程
不少java新手談到構造函數就會犯暈,咱們先來看看什麼是構造函數。設計模式
首先,構造函數是函數的一種特殊形式,特殊在哪裏?構造函數中不須要定義返回類型(void是無需返回值的意思,請注意區分二者),且構造函數的名稱與所在的類名徹底一致,其他的與函數的特性相同,能夠帶有參數列表,能夠存在函數的重載現象。函數
2.構造函數的格式學習
瞭解了構造函數的基本概念,如今來寫一個構造函數,但願你們能夠了解、記憶其格式,經過實例發現其與普通函數的不一樣之處。this
01 public class Demo{設計
02 private int num=0;對象
03 //無參構造函數繼承
04 Demo()開發
05 {
06 System.out.println("constractor_run");
07 }
08 //有參構造函數
09 Demo(int num)
10 {
11 System.out.println("constractor_args_run");
12 }
13 //普通成員函數
14 public void demoFunction()
15 {
16 System.out.println("function_run");
17 }
18 }
在這裏要說明一點,若是在類中咱們不聲明構造函數,JVM會幫咱們默認生成一個空參數的構造函數;若是在類中咱們聲明瞭帶參數列表的構造函數,JVM就不會幫咱們默認生成一個空參數的構造函數,咱們想要使用空參數的構造函數就必須本身去顯式的聲明一個空參的構造函數。
3.構造函數的做用
經過開頭的介紹,構造函數的輪廓已經漸漸清晰,那麼爲何會有構造函數呢?構造函數有什麼做用?構造函數是面向對象編程思想所需求的,它的主要做用有如下兩個:
1) 建立對象。任何一個對象建立時,都須要初始化才能使用,因此任何類想要建立實例對象就必須具備構造函數。
2) 對象初始化。構造函數能夠對對象進行初始化,而且是給與之格式(參數列表)相符合的對象初始化,是具備必定針對性的初始化函數。
4.構造函數與普通函數的區別
下面來詳細的分析下構造函數與普通函數的區別,經過二者的一個對比,但願能夠加深對構造函數的概念的理解。
1) 格式不一樣:
構造函數不存在返回類型,函數名與所在類的類名一致;
普通函數有返回類型,函數名能夠根據需求進行命名。
2)調用時期不一樣
構造函數在類的對象建立時就運行;
普通函數在對象調用時纔會執行。
3)執行次數不一樣
一個對象建立後,其構造函數只執行一次,就是建立時執行;
一個對象建立後,其普通函數能夠執行屢次,取決於對象的調用次數。
5.構造函數的使用場景
分析了那麼多構造函數的信息,那麼何時使用構造函數呢?既然構造函數是對新對象進行初始化,那麼當開發中分析事物的時候,發現事物一出現就具有了某些特徵時,就能夠將其定義在構造函數中,這樣方便快捷,也符合面向對象的編程思想。
6.構造函數在繼承中的特色
在繼承中,子類建立的對象能夠調用父類的公共方法和屬性,那麼子類會不會調用父類的構造函數呢?子類的構造函數與父類的構造函數有什麼關係?子類的構造函數須要注意些什麼問題呢?下面來解答這三個問題。
1) 子類會不會調用父類的函數?
子類繼承父類,子類對象初始化時父類的構造函數也會執行,由於子類須要使用父類中的屬性,子類須要知道是如何初始化的,因此子類初始化必然會調用父類的構造函數(除非父類沒有屬性,那麼這個類的描述也太差了點,或者沒有必要去建立這個類了)。
2) 子類的構造函數與父類的構造函數有什麼關係?
子類的構造函數中默認的第一行有一條隱式語句super(),該語句會訪問父類中的空參數構造函數,除非父類中沒有空參數的構造函數,那麼子類構造函數的第一行必須顯式調用父類的構造函數,即super(int x,…) 。
3) 子類的構造函數須要注意些什麼問題呢?
子類的構造函數中,super()語句表明調用了父類的構造函數;this()語句表明調用了子類自身的構造函數。須要注意的是,若是這兩條語句顯式寫出來必須放在構造方法的第一行,並且這兩條語句不能共存,一個構造函數中的第一行要麼是this()要麼是super()。
爲何在第一行?由於須要首先進行初始化。
爲何不能共存?由於this()表明的本類的其餘構造函數,也會去調用super(),出現了this()就沒有必要再出現super()了,重複調用沒有意義。換言之,子類中至少有一個構造函數的開頭爲super(),固然能夠隱式存在;也就是說至少有一個構造函數的開頭不是this()。
7.構造函數的擴展
以上的六條已經講構造函數的概念、特色、使用等問題介紹的比較清楚,下面來介紹幾點與構造函數相關的擴展性的小知識。
1) 全部的類都有構造函數麼?構造函數能夠被私有化麼?
既然構造函數用於建立對象而且初始化對象,那麼當一個類不須要建立對象時,就不須要定義構造函數,可是在java中,全部的類都擁有構造函數,只是有些類的構造函數對開發人員來講是隱藏不可見的,這一點與咱們的預期並不相同,不過換個角度這也很好理解,由於java是面向對象的,咱們建立類的目的就是爲了建立對象或者建立其子類對象,因此沒有構造函數的類(沒法建立對象的類)並無什麼意義。
而對於第二個問題,一個類不想要外界建立其對象時,就能夠將其構造函數私有化,本類中提供返回對象的方法,而且多數狀況下提供的對象是惟一的,單例設計模式就是一個很好的例子,而當咱們開發中須要保證對象惟一性的時候,每每就採起這種作法。
2) 構造代碼塊與構造函數有什麼類似和不一樣?
構造代碼塊用一對「{}」表示,代碼塊位置沒有具體的要求,但必須與類的成員同等級別,在括號的區域內,能夠對全部該類的對象進行初始化,也就是說該類對象建立時都會執行到該代碼塊,而且其優先於構造函數執行。構造函數如前面提到的是具備針對性的,而構造代碼塊是做用於全部本類對象的。