本篇博文主要是為新手、對(duì)java語(yǔ)言感興趣的人和那些沒(méi)有系統(tǒng)學(xué)習(xí)過(guò)java基礎(chǔ)知識(shí)的人進(jìn)行一個(gè)總結(jié),在文章中對(duì)構(gòu)造函數(shù)進(jìn)行了較為詳細(xì)的說(shuō)明和討論,也包含了我個(gè)人對(duì)于java面向?qū)ο笾袠?gòu)造函數(shù)的一些看法。希望走在java學(xué)習(xí)道路上的同行者可以有一個(gè)較為清晰的認(rèn)知和理解。當(dāng)然僅為個(gè)人觀(guān)點(diǎn),水平有限,不足之處,還請(qǐng)大家多多指出,互相交流學(xué)習(xí)。
1.構(gòu)造函數(shù)的概念
很多java新手談到構(gòu)造函數(shù)就會(huì)犯暈,我們先來(lái)看看什么是構(gòu)造函數(shù)。
首先,構(gòu)造函數(shù)是函數(shù)的一種特殊形式,特殊在哪里?構(gòu)造函數(shù)中不需要定義返回類(lèi)型(void是無(wú)需返回值的意思,請(qǐng)注意區(qū)分兩者),且構(gòu)造函數(shù)的名稱(chēng)與所在的類(lèi)名完全一致,其余的與函數(shù)的特性相同,可以帶有參數(shù)列表,可以存在函數(shù)的重載現(xiàn)象。
2.構(gòu)造函數(shù)的格式
了解了構(gòu)造函數(shù)的基本概念,現(xiàn)在來(lái)寫(xiě)一個(gè)構(gòu)造函數(shù),希望大家可以了解、記憶其格式,通過(guò)實(shí)例發(fā)現(xiàn)其與普通函數(shù)的不同之處。
01 public class Demo{
02 ? private int num=0;
03 ? //無(wú)參構(gòu)造函數(shù)
04 ? Demo()
05 {
06 System.out.println("constractor_run");
07 }
08 ? //有參構(gòu)造函數(shù)
09 ? Demo(int num)
10 {
11 System.out.println("constractor_args_run");
12 }
13 ??//普通成員函數(shù)
14 ?public void?demoFunction()
15 {
16 System.out.println("function_run");
17 }
18 }
在這里要說(shuō)明一點(diǎn),如果在類(lèi)中我們不聲明構(gòu)造函數(shù),JVM會(huì)幫我們默認(rèn)生成一個(gè)空參數(shù)的構(gòu)造函數(shù);如果在類(lèi)中我們聲明了帶參數(shù)列表的構(gòu)造函數(shù),JVM就不會(huì)幫我們默認(rèn)生成一個(gè)空參數(shù)的構(gòu)造函數(shù),我們想要使用空參數(shù)的構(gòu)造函數(shù)就必須自己去顯式的聲明一個(gè)空參的構(gòu)造函數(shù)。
3.構(gòu)造函數(shù)的作用
通過(guò)開(kāi)頭的介紹,構(gòu)造函數(shù)的輪廓已經(jīng)漸漸清晰,那么為什么會(huì)有構(gòu)造函數(shù)呢?構(gòu)造函數(shù)有什么作用?構(gòu)造函數(shù)是面向?qū)ο缶幊趟枷胨枨蟮?,它的主要作用有以下兩個(gè):
1)? 創(chuàng)建對(duì)象。任何一個(gè)對(duì)象創(chuàng)建時(shí),都需要初始化才能使用,所以任何類(lèi)想要?jiǎng)?chuàng)建實(shí)例對(duì)象就必須具有構(gòu)造函數(shù)。
2)? 對(duì)象初始化。構(gòu)造函數(shù)可以對(duì)對(duì)象進(jìn)行初始化,并且是給與之格式(參數(shù)列表)相符合的對(duì)象初始化,是具有一定針對(duì)性的初始化函數(shù)。
4.構(gòu)造函數(shù)與普通函數(shù)的區(qū)別
下面來(lái)詳細(xì)的分析下構(gòu)造函數(shù)與普通函數(shù)的區(qū)別,通過(guò)兩者的一個(gè)對(duì)比,希望可以加深對(duì)構(gòu)造函數(shù)的概念的理解。
1)? 格式不同:
構(gòu)造函數(shù)不存在返回類(lèi)型,函數(shù)名與所在類(lèi)的類(lèi)名一致;
普通函數(shù)有返回類(lèi)型,函數(shù)名可以根據(jù)需求進(jìn)行命名。
2)調(diào)用時(shí)期不同
構(gòu)造函數(shù)在類(lèi)的對(duì)象創(chuàng)建時(shí)就運(yùn)行;
普通函數(shù)在對(duì)象調(diào)用時(shí)才會(huì)執(zhí)行。
3)執(zhí)行次數(shù)不同
一個(gè)對(duì)象創(chuàng)建后,其構(gòu)造函數(shù)只執(zhí)行一次,就是創(chuàng)建時(shí)執(zhí)行;
一個(gè)對(duì)象創(chuàng)建后,其普通函數(shù)可以執(zhí)行多次,取決于對(duì)象的調(diào)用次數(shù)。
5.構(gòu)造函數(shù)的使用場(chǎng)景
分析了那么多構(gòu)造函數(shù)的信息,那么什么時(shí)候使用構(gòu)造函數(shù)呢?既然構(gòu)造函數(shù)是對(duì)新對(duì)象進(jìn)行初始化,那么當(dāng)開(kāi)發(fā)中分析事物的時(shí)候,發(fā)現(xiàn)事物一出現(xiàn)就具備了某些特征時(shí),就可以將其定義在構(gòu)造函數(shù)中,這樣方便快捷,也符合面向?qū)ο蟮木幊趟枷搿?/p>
6.構(gòu)造函數(shù)在繼承中的特點(diǎn)
在繼承中,子類(lèi)創(chuàng)建的對(duì)象可以調(diào)用父類(lèi)的公共方法和屬性,那么子類(lèi)會(huì)不會(huì)調(diào)用父類(lèi)的構(gòu)造函數(shù)呢?子類(lèi)的構(gòu)造函數(shù)與父類(lèi)的構(gòu)造函數(shù)有什么關(guān)系?子類(lèi)的構(gòu)造函數(shù)需要注意些什么問(wèn)題呢?下面來(lái)解答這三個(gè)問(wèn)題。
1)? 子類(lèi)會(huì)不會(huì)調(diào)用父類(lèi)的函數(shù)?
子類(lèi)繼承父類(lèi),子類(lèi)對(duì)象初始化時(shí)父類(lèi)的構(gòu)造函數(shù)也會(huì)執(zhí)行,因?yàn)樽宇?lèi)需要使用父類(lèi)中的屬性,子類(lèi)需要知道是如何初始化的,所以子類(lèi)初始化必然會(huì)調(diào)用父類(lèi)的構(gòu)造函數(shù)(除非父類(lèi)沒(méi)有屬性,那么這個(gè)類(lèi)的描述也太差了點(diǎn),或者沒(méi)有必要去創(chuàng)建這個(gè)類(lèi)了)。
2)? 子類(lèi)的構(gòu)造函數(shù)與父類(lèi)的構(gòu)造函數(shù)有什么關(guān)系?
子類(lèi)的構(gòu)造函數(shù)中默認(rèn)的第一行有一條隱式語(yǔ)句super(),該語(yǔ)句會(huì)訪(fǎng)問(wèn)父類(lèi)中的空參數(shù)構(gòu)造函數(shù),除非父類(lèi)中沒(méi)有空參數(shù)的構(gòu)造函數(shù),那么子類(lèi)構(gòu)造函數(shù)的第一行必須顯式調(diào)用父類(lèi)的構(gòu)造函數(shù),即super(int x,…) 。
3)? 子類(lèi)的構(gòu)造函數(shù)需要注意些什么問(wèn)題呢?
子類(lèi)的構(gòu)造函數(shù)中,super()語(yǔ)句代表調(diào)用了父類(lèi)的構(gòu)造函數(shù);this()語(yǔ)句代表調(diào)用了子類(lèi)自身的構(gòu)造函數(shù)。需要注意的是,如果這兩條語(yǔ)句顯式寫(xiě)出來(lái)必須放在構(gòu)造方法的第一行,而且這兩條語(yǔ)句不能共存,一個(gè)構(gòu)造函數(shù)中的第一行要么是this()要么是super()。
為什么在第一行?因?yàn)樾枰紫冗M(jìn)行初始化。
為什么不能共存?因?yàn)閠his()代表的本類(lèi)的其他構(gòu)造函數(shù),也會(huì)去調(diào)用super(),出現(xiàn)了this()就沒(méi)有必要再出現(xiàn)super()了,重復(fù)調(diào)用沒(méi)有意義。換言之,子類(lèi)中至少有一個(gè)構(gòu)造函數(shù)的開(kāi)頭為super(),當(dāng)然可以隱式存在;也就是說(shuō)至少有一個(gè)構(gòu)造函數(shù)的開(kāi)頭不是this()。
7.構(gòu)造函數(shù)的擴(kuò)展
以上的六條已經(jīng)講構(gòu)造函數(shù)的概念、特點(diǎn)、使用等問(wèn)題介紹的比較清楚,下面來(lái)介紹幾點(diǎn)與構(gòu)造函數(shù)相關(guān)的擴(kuò)展性的小知識(shí)。
1)? 所有的類(lèi)都有構(gòu)造函數(shù)么?構(gòu)造函數(shù)可以被私有化么?
既然構(gòu)造函數(shù)用于創(chuàng)建對(duì)象并且初始化對(duì)象,那么當(dāng)一個(gè)類(lèi)不需要?jiǎng)?chuàng)建對(duì)象時(shí),就不需要定義構(gòu)造函數(shù),但是在java中,所有的類(lèi)都擁有構(gòu)造函數(shù),只是有些類(lèi)的構(gòu)造函數(shù)對(duì)開(kāi)發(fā)人員來(lái)說(shuō)是隱藏不可見(jiàn)的,這一點(diǎn)與我們的預(yù)期并不相同,不過(guò)換個(gè)角度這也很好理解,因?yàn)閖ava是面向?qū)ο蟮?,我們?chuàng)建類(lèi)的目的就是為了創(chuàng)建對(duì)象或者創(chuàng)建其子類(lèi)對(duì)象,所以沒(méi)有構(gòu)造函數(shù)的類(lèi)(無(wú)法創(chuàng)建對(duì)象的類(lèi))并沒(méi)有什么意義。
而對(duì)于第二個(gè)問(wèn)題,一個(gè)類(lèi)不想要外界創(chuàng)建其對(duì)象時(shí),就可以將其構(gòu)造函數(shù)私有化,本類(lèi)中提供返回對(duì)象的方法,并且多數(shù)情況下提供的對(duì)象是唯一的,單例設(shè)計(jì)模式就是一個(gè)很好的例子,而當(dāng)我們開(kāi)發(fā)中需要保證對(duì)象唯一性的時(shí)候,往往就采取這種做法。
2)? 構(gòu)造代碼塊與構(gòu)造函數(shù)有什么相似和不同?
構(gòu)造代碼塊用一對(duì)“{}”表示,代碼塊位置沒(méi)有具體的要求,但必須與類(lèi)的成員同等級(jí)別,在括號(hào)的區(qū)域內(nèi),可以對(duì)所有該類(lèi)的對(duì)象進(jìn)行初始化,也就是說(shuō)該類(lèi)對(duì)象創(chuàng)建時(shí)都會(huì)執(zhí)行到該代碼塊,并且其優(yōu)先于構(gòu)造函數(shù)執(zhí)行。構(gòu)造函數(shù)如前面提到的是具有針對(duì)性的,而構(gòu)造代碼塊是作用于所有本類(lèi)對(duì)象的。