版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第5章類(lèi)的基本形式5.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本概念
5.2類(lèi)與對(duì)象
5.3類(lèi)的封裝性
5.4在類(lèi)內(nèi)部調(diào)用方法
5.5引用數(shù)據(jù)類(lèi)型的傳遞5.6匿名對(duì)象5.7構(gòu)造方法5.8對(duì)象的比較5.9this關(guān)鍵字的使用5.10static關(guān)鍵字的使用5.11構(gòu)造方法的私有5.12對(duì)象數(shù)組的使用
5.1面向?qū)ο蟪绦蛟O(shè)計(jì)的基本概念
早期的程序設(shè)計(jì)經(jīng)歷了“面向問(wèn)題”、“面向過(guò)程”的階段,隨著計(jì)算機(jī)技術(shù)的發(fā)展,以及所要解決問(wèn)題的復(fù)雜性的提高,以往的程序設(shè)計(jì)方法已經(jīng)不能適應(yīng)這種發(fā)展的需求,于是從20世紀(jì)70年代開(kāi)始,相繼出現(xiàn)了多種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言(如圖5-1所示),并逐漸產(chǎn)生了面向?qū)ο蟮某绦蛟O(shè)計(jì)方法。面向?qū)ο蟮某绦蛟O(shè)計(jì)涉及對(duì)象、封裝、類(lèi)、繼承及多態(tài)等基本概念。圖5-1計(jì)算機(jī)語(yǔ)言的發(fā)展過(guò)程5.1.1對(duì)象
何謂面向?qū)ο竽??面向?qū)ο蟪绦蛟O(shè)計(jì)是將人們認(rèn)識(shí)世界過(guò)程中普遍采用的思維方法應(yīng)用到程序設(shè)計(jì)中。對(duì)象是現(xiàn)實(shí)世界中存在的事物,它們是有形的,如某個(gè)人、某種物品,也可以是無(wú)形的,如某項(xiàng)計(jì)劃、某次商業(yè)交易。對(duì)象是構(gòu)成現(xiàn)實(shí)世界的一個(gè)獨(dú)立單位,人們對(duì)世界的認(rèn)識(shí),是從分析對(duì)象的特征入手的。
對(duì)象的特征分為靜態(tài)特征和動(dòng)態(tài)特征兩種。靜態(tài)特征指對(duì)象的外觀、性質(zhì)、屬性等;動(dòng)態(tài)特征指對(duì)象具有的功能、行為等??陀^事物是錯(cuò)綜復(fù)雜的,但人們總是從某一目的出發(fā),運(yùn)用抽象分析的能力,從眾多特征中抽取最具代表性、最能反映對(duì)象本質(zhì)的若干特征加以詳細(xì)研究。人們將對(duì)象的靜態(tài)特征抽象為屬性,用數(shù)據(jù)來(lái)描述,在Java語(yǔ)言中稱(chēng)之為變量;人們將對(duì)象的動(dòng)態(tài)特征抽象為行為,用一組代碼來(lái)表示,完成對(duì)數(shù)據(jù)的操作,在Java語(yǔ)言中稱(chēng)之為方法。一個(gè)對(duì)象由一組屬性和一組對(duì)屬性進(jìn)行操作的方法構(gòu)成。
5.1.2類(lèi)
具有相同屬性及相同行為的一組對(duì)象稱(chēng)為類(lèi)。廣義地講,具有共同性質(zhì)的事物的集合稱(chēng)為類(lèi)。在面向?qū)ο蟪绦蛟O(shè)計(jì)中,類(lèi)是一個(gè)獨(dú)立的單位,它有一個(gè)類(lèi)名,其內(nèi)部包括成員變量,用于描述對(duì)象的屬性,還包括類(lèi)的成員方法,用于描述對(duì)象的行為。在Java程序設(shè)計(jì)中,類(lèi)被認(rèn)為是一種抽象數(shù)據(jù)類(lèi)型,這種數(shù)據(jù)類(lèi)型不但包括數(shù)據(jù),還包括方法。這大大擴(kuò)充了數(shù)據(jù)類(lèi)型的概念。
類(lèi)是一個(gè)抽象的概念,要利用類(lèi)的方式來(lái)解決問(wèn)題,必須用類(lèi)創(chuàng)建一個(gè)實(shí)例化的類(lèi)對(duì)象,然后通過(guò)類(lèi)對(duì)象去訪問(wèn)類(lèi)的成員變量,去調(diào)用類(lèi)的成員方法來(lái)實(shí)現(xiàn)程序的功能。這類(lèi)同于“汽車(chē)”本身是一個(gè)抽象的概念,只有使用了一輛具體的汽車(chē),才能感受到汽車(chē)的功能。一個(gè)類(lèi)可創(chuàng)建多個(gè)類(lèi)對(duì)象,它們具有相同的屬性模式,但可以具有不同的屬性值。Java程序?yàn)槊恳粋€(gè)類(lèi)對(duì)象都開(kāi)辟了內(nèi)存空間,以便保存各自的屬性值。
面向?qū)ο蟮某绦蛟O(shè)計(jì)具有如下三個(gè)主要特征:
(1)封裝性;
(2)繼承性;
(3)多態(tài)性。5.1.3封裝性
封裝是面向?qū)ο蟮姆椒ㄋ鶓?yīng)遵循的一個(gè)重要原則。它有兩個(gè)含義:一是指把對(duì)象的屬性和行為看成一個(gè)密不可分的整體,將這兩者“封裝”在一個(gè)不可分割的獨(dú)立單位(即對(duì)象)中;另一層含義指“信息隱蔽”,把不需要讓外界知道的信息隱藏起來(lái)。有些對(duì)象的屬性及行為允許外界用戶知道或使用,但不允許更改,而另一些屬性或行為則不允許外界知曉,或只允許使用對(duì)象的功能,而盡可能隱蔽對(duì)象的功能實(shí)現(xiàn)細(xì)節(jié)。封裝機(jī)制在程序設(shè)計(jì)中表現(xiàn)為,把描述對(duì)象屬性的變量及實(shí)現(xiàn)對(duì)象功能的方法合在一起,定義為一個(gè)程序單位,并保證外界不能任意更改其內(nèi)部的屬性值,也不能任意調(diào)動(dòng)其內(nèi)部的方法。封裝機(jī)制的另一個(gè)特點(diǎn)是:為封裝在一個(gè)整體內(nèi)的變量及方法規(guī)定了不同級(jí)別的“可見(jiàn)性”或訪問(wèn)權(quán)限。
5.1.4繼承性
繼承是面向?qū)ο蠓椒ㄖ械闹匾拍?,并且是提高軟件開(kāi)發(fā)效率的重要手段。首先擁有反映事物一般特性的類(lèi),然后在其基礎(chǔ)上派生出反映特殊事物的類(lèi)。例如,已有汽車(chē)的類(lèi),該類(lèi)中描述了汽車(chē)的普遍屬性和行為,進(jìn)一步再產(chǎn)生轎車(chē)的類(lèi),轎車(chē)的類(lèi)繼承于汽車(chē)類(lèi),轎車(chē)類(lèi)不但擁有汽車(chē)類(lèi)的全部屬性和行為,還增加了轎車(chē)特有的屬性和行為。在Java程序設(shè)計(jì)中,已有的類(lèi)可以是Java開(kāi)發(fā)環(huán)境所提供的一批最基本的程序—類(lèi)庫(kù)。用戶開(kāi)發(fā)的程序類(lèi)繼承這些已有的類(lèi)。這樣現(xiàn)在類(lèi)所描述過(guò)的屬性及行為,即已定義的變量和方法,在繼承產(chǎn)生的類(lèi)中完全可以使用。被繼承的類(lèi)稱(chēng)為父類(lèi)或超類(lèi),而經(jīng)繼承產(chǎn)生的類(lèi)稱(chēng)為子類(lèi)或派生類(lèi)。根據(jù)繼承機(jī)制,派生類(lèi)繼承了超類(lèi)的所有成員,并相應(yīng)地增加了自己的一些新的成員。面向?qū)ο蟪绦蛟O(shè)計(jì)中的繼承機(jī)制大大增強(qiáng)了程序代碼的可復(fù)用性,提高了軟件的開(kāi)發(fā)效率,降低了程序產(chǎn)生錯(cuò)誤的可能性,也為程序的修改擴(kuò)充提供了便利。若一個(gè)子類(lèi)只允許繼承一個(gè)父類(lèi),稱(chēng)為單繼承;若允許繼承多個(gè)父類(lèi),稱(chēng)為多繼承。目前許多面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言不支持多繼承。Java語(yǔ)言通過(guò)接口(interface)的方式來(lái)彌補(bǔ)由于Java不支持多繼承而帶來(lái)的子類(lèi)不能享用多個(gè)父類(lèi)成員的缺憾。5.1.5類(lèi)的多態(tài)性
多態(tài)是面向?qū)ο蟪绦蛟O(shè)計(jì)的又一個(gè)重要特征。多態(tài)是指允許程序中出現(xiàn)重名現(xiàn)象。Java語(yǔ)言中含有方法重載與成員覆蓋兩種形式的多態(tài)。方法重載是指在一個(gè)類(lèi)中,允許多個(gè)方法使用同一個(gè)名字,但方法的參數(shù)不同,完成的功能也不同。成員覆蓋是指子類(lèi)與父類(lèi)允許具有相同的變量名稱(chēng),但數(shù)據(jù)類(lèi)型不同,允許具有相同的方法名稱(chēng),但完成的功能不同。
多態(tài)的特性使程序的抽象程度和簡(jiǎn)捷程度更高,有助于程序設(shè)計(jì)人員對(duì)程序的分組進(jìn)行協(xié)同開(kāi)發(fā)。 5.2類(lèi)與對(duì)象
面向?qū)ο蟮木幊趟枷肓D使在計(jì)算機(jī)語(yǔ)言中對(duì)事物的描述與現(xiàn)實(shí)世界中該事物的本來(lái)面目盡可能地一致,類(lèi)(class)和對(duì)象(object)就是面向?qū)ο蠓椒ǖ暮诵母拍睢?/p>
類(lèi)是對(duì)某一類(lèi)事物的描述,是抽象的、概念上的定義;對(duì)象是實(shí)際存在的該類(lèi)事物的個(gè)體,因而也稱(chēng)實(shí)例(Instance)。圖5-2就是一個(gè)說(shuō)明類(lèi)與對(duì)象的典型范例。
圖5-2中,汽車(chē)設(shè)計(jì)圖就是“類(lèi)”,由這個(gè)圖紙?jiān)O(shè)計(jì)出來(lái)的若干汽車(chē)就是按照該類(lèi)產(chǎn)生的“對(duì)象”。圖5-2類(lèi)與對(duì)象的實(shí)例化說(shuō)明5.2.1類(lèi)的聲明
在使用類(lèi)之前,必須先定義它,然后才可利用所定義的類(lèi)來(lái)聲明變量,并創(chuàng)建對(duì)象。類(lèi)定義的語(yǔ)法如下:程序說(shuō)明:
(1)用class聲明了一個(gè)名為Person的類(lèi),這里Person是類(lèi)的名稱(chēng)。
(2)第3、4行聲明了兩個(gè)屬性name和age,name為String型(字符串類(lèi)型),age為int型(整型)。
(3)第5~8行聲明了一個(gè)talk()方法,此方法用于向屏幕打印信息。
為了更好地說(shuō)明類(lèi)的關(guān)系,請(qǐng)參見(jiàn)圖5-3。圖5-3Person類(lèi)圖5.2.2創(chuàng)建新的對(duì)象
在實(shí)際中單單有類(lèi)是不夠的,類(lèi)提供的只是一個(gè)模板,必須依照它創(chuàng)建出對(duì)象之后才可以使用。下面定義了由類(lèi)產(chǎn)生對(duì)象的基本形式:
類(lèi)名對(duì)象名=new類(lèi)名();
創(chuàng)建屬于某類(lèi)的對(duì)象,需要通過(guò)下面兩個(gè)步驟來(lái)實(shí)現(xiàn):
(1)聲明指向“由類(lèi)所創(chuàng)建的對(duì)象”的變量。
(2)利用new創(chuàng)建新的對(duì)象,并指派給先前所創(chuàng)建的變量。
如果要?jiǎng)?chuàng)建Person類(lèi)的對(duì)象,可用下列的語(yǔ)句來(lái)實(shí)現(xiàn):
Personp; //先聲明一個(gè)Person類(lèi)的對(duì)象p
p=newPerson(); //用new關(guān)鍵字實(shí)例化Person類(lèi)的對(duì)象p
當(dāng)然也可以用下面這種形式來(lái)聲明變量:
Personp=newPerson(); //聲明Person對(duì)象p并直接實(shí)例化此對(duì)象
對(duì)象只有在實(shí)例化之后才能被使用,而實(shí)例化對(duì)象的關(guān)鍵字就是new。對(duì)象實(shí)例化過(guò)程如圖5-4所示。圖5-4Person類(lèi)對(duì)象的實(shí)例化過(guò)程由圖5-4可以看出,當(dāng)語(yǔ)句執(zhí)行到Personp時(shí),只是在棧內(nèi)存中聲明了一個(gè)Person的對(duì)象p,但是這時(shí)p并沒(méi)有在堆內(nèi)存中開(kāi)辟空間,所以這時(shí)的p是一個(gè)未實(shí)例化的對(duì)象,用new關(guān)鍵字實(shí)際上就是開(kāi)辟堆內(nèi)存,把堆內(nèi)存的引用賦給了p,這時(shí)的p才稱(chēng)為實(shí)例化對(duì)象。
如果要訪問(wèn)對(duì)象中的某個(gè)成員變量或方法,可以通過(guò)下面語(yǔ)法來(lái)實(shí)現(xiàn):
訪問(wèn)屬性:對(duì)象名稱(chēng).屬性名。
訪問(wèn)方法:對(duì)象名稱(chēng).方法名()。輸出結(jié)果:
我是:張三,今年:25歲
程序說(shuō)明:
(1)第6行聲明了一個(gè)Person類(lèi)的實(shí)例對(duì)象p,并直接實(shí)例化此對(duì)象。
(2)第7、8行給p對(duì)象中的屬性賦值。
(3)第9行調(diào)用talk()方法,在屏幕上輸出信息。
參照上述程序代碼與圖5-5的內(nèi)容即可了解到Java是如何對(duì)對(duì)象成員進(jìn)行訪問(wèn)操作的。圖5-5對(duì)Person對(duì)象p的訪問(wèn)操作過(guò)程5.2.3創(chuàng)建多個(gè)新對(duì)象
在例5-3的程序中,只建立了一個(gè)Person的對(duì)象p,如果需要?jiǎng)?chuàng)建多個(gè)對(duì)象,則可以依照由類(lèi)產(chǎn)生對(duì)象的基本形式產(chǎn)生多個(gè)對(duì)象。
【例5-4】
TestPersonDemo1.java。程序說(shuō)明:
(1)第1~9行聲明了一個(gè)新的類(lèi)Person,類(lèi)中有name、age兩個(gè)屬性,還有一個(gè)talk()方法用于輸出信息。
(2)第14~15行聲明了Person的兩個(gè)實(shí)例對(duì)象p1、p2。
(3)第17、18行給p1對(duì)象的屬性賦值。
(4)第20、21行給p2對(duì)象的屬性賦值。
(5)第23、24行分別用p1、p2調(diào)用Person類(lèi)中的talk()方法,用于在屏幕上打印信息。
上述程序首先聲明了兩個(gè)對(duì)象p1和p2,之后分別為p1與p2賦值??梢园l(fā)現(xiàn),p1與p2賦的值互不影響,此關(guān)系可由圖5-6表示出來(lái)。圖5-6Person中p1與p2的內(nèi)存分配圖案例1對(duì)象組合案例
【案例描述】
編寫(xiě)一個(gè)Circle類(lèi),該類(lèi)的對(duì)象可以計(jì)算圓的面積。
【代碼與注釋】
程序名稱(chēng)為Circle.java。
程序代碼如下: 5.3類(lèi)?的?封?裝?性
【例5-5】
TestPersonDemo2.java。輸出結(jié)果:
我是:張三,今年:-25歲
程序說(shuō)明:
(1)第1~9行聲明了一個(gè)新的類(lèi)Person,類(lèi)中有name、age兩個(gè)屬性,還有一個(gè)talk()方法用于輸出信息。
(2)第15行聲明并實(shí)例化Person的對(duì)象p。
(3)第17~21行分別為p對(duì)象中的屬性賦值,并調(diào)用talk()方法。
由上面的程序可以看出,在程序的第19行將年齡(age)賦值為-25,這明顯是一個(gè)不合法的數(shù)據(jù),最終程序在調(diào)用talk()方法時(shí)才會(huì)打印出這種錯(cuò)誤的信息。程序說(shuō)明:
(1)第1~9行聲明了一個(gè)新的類(lèi)Person,類(lèi)中有name、age兩個(gè)屬性,還有一個(gè)talk()方法用于輸出信息。與前面不同的是,這里的屬性在聲明時(shí)前面都加上了private關(guān)鍵字。
(2)第15行聲明并實(shí)例化Person類(lèi)的對(duì)象p。
(3)第17~21行分別為p對(duì)象中的屬性賦值,并調(diào)用talk()方法。
可以看出,本程序與例5-5除了在聲明屬性上有些區(qū)別外,并沒(méi)有其他區(qū)別,而就是這一個(gè)小小的關(guān)鍵字,導(dǎo)致程序連編譯都無(wú)法通過(guò),所提示的錯(cuò)誤為:屬性(name、age)為私有的,所以不能由對(duì)象直接進(jìn)行訪問(wèn)。程序說(shuō)明:
(1)第9~25行加入了一些setXxx()、getXxx()方法,主要用來(lái)設(shè)置和取得類(lèi)中的私有屬性。
(2)第13~17行設(shè)置年齡時(shí)在程序中加了判斷語(yǔ)句,如果傳入的數(shù)值大于0,則將值賦給age屬性。
(3)第35行調(diào)用了Person類(lèi)中的setName()方法,并賦值為“張三”。
(4)第37行調(diào)用了setAge()方法,同時(shí)傳進(jìn)了一個(gè)-25的不合理年齡。
可以發(fā)現(xiàn)在本程序中,傳進(jìn)了一個(gè)-25的不合理數(shù)值,這樣在設(shè)置Person中的屬性時(shí)因?yàn)椴粷M足條件而不能被設(shè)置成功,所以age的值依然為自己的默認(rèn)值0。這樣在輸出時(shí)可以發(fā)現(xiàn),那些錯(cuò)誤的數(shù)據(jù)并沒(méi)有被賦到屬性上,而只輸出了默認(rèn)值。用private聲明的屬性或方法只能在其類(lèi)的內(nèi)部被調(diào)用,而不能在類(lèi)的外部被調(diào)用。讀者可以先暫時(shí)簡(jiǎn)單理解為:在類(lèi)的外部不能用對(duì)象去調(diào)用private聲明的屬性或方法。下面程序修改自例5-7,在這里將talk()方法封裝了起來(lái)。
【例5-8】
TestPersonDemo4.java。程序說(shuō)明:
(1)第5行將talk()方法用private來(lái)聲明。
(2)第9~25行加入了一些setXxx()、getXxx()方法,主要用來(lái)設(shè)置和取得類(lèi)中的私有屬性。
(3)第13~17行設(shè)置年齡時(shí)在程序中加了判斷語(yǔ)句,如果傳入的數(shù)值大于0,則將值賦給age屬性。
(4)第35行調(diào)用了類(lèi)Person中的setName()方法,并賦值為“張三”。
(5)第37行調(diào)用了setAge()方法,同時(shí)傳進(jìn)了一個(gè)不合理的年齡-25。 5.4在類(lèi)內(nèi)部調(diào)用方法
在一個(gè)Java程序中是可以通過(guò)對(duì)象去調(diào)用類(lèi)中的方法的,當(dāng)然類(lèi)的內(nèi)部也能互相調(diào)用各自的方法。例如,下面的程序修改自以前的程序代碼,新增加了一個(gè)公有的say()方法,并用這個(gè)方法去調(diào)用私有的talk()方法。
【例5-9】
TestPersonDemo5.java。輸出結(jié)果:
我是:張三,今年:30歲
程序說(shuō)明:
(1)第9~12行聲明公有方法say(),此方法用于調(diào)用類(lèi)內(nèi)部的私有方法talk()。
(2)第42行調(diào)用Person類(lèi)中的say()方法,其實(shí)也就是調(diào)用Person類(lèi)中的talk()方法。 5.5引用數(shù)據(jù)類(lèi)型的傳遞
Java中使用引用來(lái)取代C++?中的指針,那么什么是引用呢?Java又是怎樣通過(guò)引用來(lái)取代C++?中的指針的呢?
【例5-10】
TestRefDemo1.java。
程序說(shuō)明:
(1)第1~5行聲明Person類(lèi),有name與age兩個(gè)屬性。
(2)第11、13行分別聲明兩個(gè)Person的對(duì)象p1和p2,但這兩個(gè)對(duì)象在聲明時(shí)都同時(shí)賦值為null,表示此對(duì)象未實(shí)例化。
(3)第15行對(duì)對(duì)象p1進(jìn)行實(shí)例化。
(4)第17、18行分別為p1對(duì)象中的屬性賦值。
(5)第20行將p1的引用賦給p2,此時(shí)相當(dāng)于p1與p2都同時(shí)指向同一塊堆內(nèi)存。
(6)第22、23行分別調(diào)用和p2.age,輸出p2對(duì)象中的屬性。
(7)第24行把p1對(duì)象賦值為null,表示此對(duì)象不再引用任何內(nèi)存空間。
程序執(zhí)行到第24行時(shí),實(shí)際上p1斷開(kāi)了對(duì)其之前實(shí)例化對(duì)象的引用,而p2則繼續(xù)指向p1原先的引用。
由上述程序可以看出,在程序中并未用new關(guān)鍵字為對(duì)象p2實(shí)例化,到最后依然可以用與p2.age方式輸出屬性的內(nèi)容,且內(nèi)容與p1對(duì)象中的內(nèi)容相似。也就是說(shuō),在上述程序中p2是通過(guò)p1對(duì)象實(shí)例化的,或者說(shuō)p1將其自身的引用傳遞給了p2,如圖5-7所示。圖5-7引用數(shù)據(jù)類(lèi)型的傳遞如果在程序最后又加了一段代碼,令p2=null,則之前由p1創(chuàng)建的實(shí)例化對(duì)象不再有任何對(duì)象使用它,此對(duì)象稱(chēng)為垃圾對(duì)象,如圖5-8所示。圖5-8垃圾對(duì)象的產(chǎn)生所謂垃圾對(duì)象,就是指程序中不再使用的對(duì)象引用。
【例5-11】TestRefDemo2.java。程序說(shuō)明:
(1)第1~4行聲明一個(gè)名為Change的類(lèi),其有一個(gè)屬性x。
(2)第9行實(shí)例化了一個(gè)Change類(lèi)的對(duì)象c。
(3)第10行將對(duì)象c中的x屬性賦值為20。
(4)第11行調(diào)用fun()方法將對(duì)象c傳遞到方法中。
(5)第14~17行聲明fun方法,接收參數(shù)類(lèi)型為Change類(lèi)型。
(6)第16行將對(duì)象c1中的x屬性賦值為25。
程序最后的輸出結(jié)果為“x=25”,而程序只有在fun()方法中才將x的值賦為25,為什么方法完成之后值依然被保留了下來(lái)呢?讀者可以發(fā)現(xiàn)在程序第14行,fun()方法接收的參數(shù)是Changec1,也就是說(shuō)fun()方法接收的是一個(gè)對(duì)象的引用。所以在fun方法中所做的操作會(huì)影響原先的參數(shù)。可以參考圖5-9來(lái)了解整個(gè)過(guò)程。圖5-9操作過(guò)程
5.6匿名對(duì)象
顧名思義,匿名對(duì)象就是沒(méi)有明確聲明的對(duì)象。讀者也可以簡(jiǎn)單地理解為只使用一次的對(duì)象,即沒(méi)有任何一個(gè)具體的對(duì)象名稱(chēng)引用它。
【例5-12】TestNoName.java。程序說(shuō)明:
(1)第1~9行聲明了Person類(lèi),其有name與age兩個(gè)私有屬性,并分別賦了初值。
(2)第14行聲明了Person匿名對(duì)象,調(diào)用Person類(lèi)中的talk()方法。
從程序中可以看出,用newPerson()聲明的對(duì)象并沒(méi)有賦給任何一個(gè)Person類(lèi)對(duì)象的引用,所以此對(duì)象只使用了一次,之后就會(huì)被Java的垃圾收集器回收。
5.7構(gòu)造方法
1.構(gòu)造方法的定義
在Java程序中,構(gòu)造方法所完成的主要工作是幫助新創(chuàng)建的對(duì)象賦初值。構(gòu)造方法可視為一種特殊的方法,它的定義方式與普通方法類(lèi)似,其語(yǔ)法如下:在使用構(gòu)造方法時(shí)應(yīng)注意以下幾點(diǎn):
(1)它具有與類(lèi)名相同的名稱(chēng)。
(2)它沒(méi)有返回值。
構(gòu)造方法沒(méi)有返回值,其名稱(chēng)必須與類(lèi)的名稱(chēng)相同,它的調(diào)用時(shí)機(jī)與一般方法不同。一般方法是在需要時(shí)才調(diào)用,而構(gòu)造方法則是在創(chuàng)建對(duì)象時(shí)便自動(dòng)調(diào)用,并執(zhí)行構(gòu)造方法的內(nèi)容。因此,構(gòu)造方法無(wú)需在程序中直接調(diào)用,而是在對(duì)象產(chǎn)生時(shí)自動(dòng)執(zhí)行。
基于上述構(gòu)造方法的特性,可利用它來(lái)對(duì)對(duì)象的數(shù)據(jù)成員進(jìn)行初始化賦值。所謂初始化,就是為對(duì)象賦初值。
下面的程序說(shuō)明了構(gòu)造方法的使用。
【例5-13】TestConstruct.java。從上述程序中讀者不難發(fā)現(xiàn),在類(lèi)中聲明的構(gòu)造方法會(huì)在實(shí)例化對(duì)象時(shí)自動(dòng)調(diào)用。讀者可能會(huì)問(wèn),在之前的程序中用同樣的方法來(lái)產(chǎn)生對(duì)象,但是在類(lèi)中并沒(méi)有聲明任何構(gòu)造方法,而程序不也一樣正常運(yùn)行了嗎?實(shí)際上,讀者在執(zhí)行javac編譯Java程序時(shí),如果在程序中沒(méi)有明確聲明構(gòu)造方法,則系統(tǒng)會(huì)自動(dòng)為類(lèi)加入一個(gè)無(wú)參的且什么都不做的構(gòu)造方法,類(lèi)似于下面代碼:
publicPerson(){}
所以,之前的程序雖然沒(méi)有明確聲明構(gòu)造方法,也是可以正常運(yùn)行的。
2.構(gòu)造方法的重載
在Java中,不僅普通方法可以重載,構(gòu)造方法也可以重載。只要構(gòu)造方法的參數(shù)個(gè)數(shù)不同,或是類(lèi)型不同,便可定義多個(gè)名稱(chēng)相同的構(gòu)造方法。這種做法在Java中是常見(jiàn)的。
【例5-14】TestConstruct1.java。
(3)第20行調(diào)用Person類(lèi)中含有兩個(gè)參數(shù)的構(gòu)造方法(newPerson("張三",25)),同時(shí)將姓名和年齡傳到類(lèi)中,分別為各個(gè)屬性賦值。
(4)第21行調(diào)用Person類(lèi)中的talk()方法,并打印信息。
從上述程序可以看出,構(gòu)造方法的基本作用就是為類(lèi)中的屬性初始化,在程序產(chǎn)生類(lèi)的實(shí)例對(duì)象時(shí),將需要的參數(shù)由構(gòu)造方法傳入,之后再由構(gòu)造方法為其內(nèi)部的屬性進(jìn)行初始化。這是在一般開(kāi)發(fā)中經(jīng)常使用的技巧,但是這里有一個(gè)問(wèn)題是讀者應(yīng)該注意的,請(qǐng)看下面的程序。
【例5-15】TestConstruct2.java??梢钥闯觯诰幾g程序第20行(Personp=newPerson())時(shí)發(fā)生了錯(cuò)誤,這個(gè)錯(cuò)誤說(shuō)找不到Person類(lèi)的無(wú)參構(gòu)造方法。前面曾經(jīng)提過(guò),如果程序中沒(méi)有聲明構(gòu)造方法,程序就會(huì)自動(dòng)聲明一個(gè)無(wú)參的且什么都不做的構(gòu)造方法,可是現(xiàn)在卻發(fā)生了找不到無(wú)參構(gòu)造方法的問(wèn)題,這是為什么呢?讀者可以發(fā)現(xiàn)第5~10行已經(jīng)聲明了一個(gè)含有兩個(gè)參數(shù)的構(gòu)造方法。在Java程序中只要明確聲明了構(gòu)造方法,則默認(rèn)的構(gòu)造方法將不會(huì)被自動(dòng)生成。要解決這一問(wèn)題,只需要簡(jiǎn)單修改一下Person類(lèi)即可,可以在Person類(lèi)中明確地聲明一無(wú)參的且什么都不做的構(gòu)造方法。
【例5-16】TestConstruct2.java。 5.8對(duì)?象?的?比?較
對(duì)象間的比較有兩種方式,即“==”運(yùn)算符與equals()方法。“==”操作符用于比較兩個(gè)對(duì)象的內(nèi)存地址值是否相等,equals()方法用于比較兩個(gè)對(duì)象的內(nèi)容是否一致。
【例5-17】TestEquals.java。由程序的輸出結(jié)果可以看出,str1不等于str2。有些讀者可能會(huì)問(wèn),str1與str2的內(nèi)容完全一樣,為什么會(huì)不等于呢?程序第5行和第6行分別實(shí)例化了String類(lèi)的兩個(gè)對(duì)象,此時(shí)這兩個(gè)對(duì)象指向不同的內(nèi)存空間,所以它們的內(nèi)存地址是不一樣的。這時(shí)程序中用的是“==”比較,比較的是內(nèi)存地址值,所以輸出str1!=str2。程序第7行將str2的引用賦給str3,這時(shí)就相當(dāng)于str3也指向了str2的引用,這兩個(gè)對(duì)象指向的是同一內(nèi)存地址,所以比較值的結(jié)果是str2==str3。
那么該如何去比較其中的內(nèi)容呢?這就需要采用另外一種方式—equals()方法。
【例5-18】TestEquals1.java。輸出結(jié)果:
str1equalsstr2
str2equalsstr3
可以看出,在程序中將比較方式換成了equals(),而且調(diào)用equals()方法的是String類(lèi)的對(duì)象,所以可知equals()是String類(lèi)中的方法。特別注意:“==”用于比較內(nèi)存地址值,“equals()”用于比較內(nèi)容。
下面兩種String對(duì)象的聲明方式到底有什么不同?
Stringstr1=newString("java");
Stringstr2="java";
下面先來(lái)看一個(gè)例子。
【例5-19】StringDemo.java。圖5-10String對(duì)象的聲明與使用由圖5-10中可以看出,“java”這個(gè)字符串在內(nèi)存中開(kāi)辟一個(gè)空間,而str1與str3又同時(shí)指向同一內(nèi)存空間,所以即使str1與str3是分兩次聲明的,但最終都指向了同一內(nèi)存空間。str2用new關(guān)鍵字來(lái)開(kāi)辟空間,所以單獨(dú)占有自己的一個(gè)內(nèi)存空間。
另外,要注意的是,String對(duì)象的內(nèi)容一旦聲明,就不能輕易改變。如果要改變一個(gè)String對(duì)象的值,第一步要做的是將原有的String引用斷開(kāi),之后再開(kāi)辟新的內(nèi)存空間,而且如果用new關(guān)鍵字開(kāi)辟String對(duì)象的內(nèi)存空間,則實(shí)際上就開(kāi)辟了兩個(gè)內(nèi)存空間,如圖5-11所示。圖5-11String對(duì)象內(nèi)容的改變 5.9this關(guān)鍵字的使用
1.this的本質(zhì)
在整個(gè)Java的面向?qū)ο蟪绦蛟O(shè)計(jì)中,this是一個(gè)比較難理解的關(guān)鍵字,它表示當(dāng)前對(duì)象,而所謂的當(dāng)前對(duì)象,就是指調(diào)用類(lèi)中方法或?qū)傩缘哪莻€(gè)對(duì)象。
【例5-20】Person.java。
Person-1.java這段代碼與Person.java的不同之處在于在第7、8行分別加上了this關(guān)鍵字。此時(shí)的和this.age就分別代表類(lèi)中的name與age屬性,這時(shí)再完成賦值操作,就可以清楚地知道誰(shuí)賦值給誰(shuí)。完整的程序代碼如下例所示。
【例5-22】TestJavaThis.java。程序說(shuō)明:
(1)第1~14行聲明了一個(gè)名為Person的類(lèi)。
(2)第5~9行聲明Person類(lèi)的一個(gè)構(gòu)造方法。此構(gòu)造方法的作用是為類(lèi)中的屬性賦初值。為了更好地說(shuō)明this是表示當(dāng)前對(duì)象的,下面再舉一個(gè)例子:判斷兩個(gè)對(duì)象是否相等,在這里假設(shè)只要姓名、年齡都相同就為同一個(gè)人,否則不是同一個(gè)人。程序說(shuō)明:
(1)第1~21行聲明了一個(gè)名為Person的類(lèi),其中有一個(gè)構(gòu)造方法與一個(gè)比較方法。
(2)第10~20行在Person類(lèi)中聲明了一個(gè)compare方法,此方法接收Person實(shí)例對(duì)象的引用。
(3)第12行比較姓名和年齡是否同時(shí)相等。
(4)第28行由p1調(diào)用compare方法,將p2傳入到compare方法之中,所以在程序中第12行的就代表,this.age就代表p1.age,而傳入的參數(shù)p2則被compare方法中的參數(shù)p表示。
由此不難理解,this表示當(dāng)前對(duì)象這一重要概念,所以程序最后輸出了“相等,是同一人!”的正確判斷信息。
2.用this調(diào)用構(gòu)造方法
如果要在程序中用某一構(gòu)造方法調(diào)用另一構(gòu)造方法,可以用this來(lái)實(shí)現(xiàn),具體的調(diào)用形式如下:
this();
【例5-24】TestJavaThis1.java。程序說(shuō)明:
(1)第1~17行聲明一個(gè)名為Person的類(lèi),類(lèi)中聲明了一個(gè)無(wú)參和一個(gè)有參兩個(gè)構(gòu)造方法。
(2)第12行使用this調(diào)用本類(lèi)中的無(wú)參構(gòu)造方法。
(3)第22行聲明一個(gè)Person類(lèi)的匿名對(duì)象,調(diào)用了有參的構(gòu)造方法。
從上述程序可以看出,在第22行雖然調(diào)用了Person中有兩個(gè)參數(shù)的構(gòu)造方法,但是由于第12行使用了this調(diào)用本類(lèi)中的無(wú)參構(gòu)造方法,所以程序先去執(zhí)行Person中的無(wú)參構(gòu)造方法,之后再去繼續(xù)執(zhí)行其他構(gòu)造方法。如果把this調(diào)用無(wú)參構(gòu)造方法的位置任意調(diào)換,則可以在任何時(shí)候調(diào)用構(gòu)造方法嗎?實(shí)際上這樣理解是錯(cuò)誤的。構(gòu)造方法是在實(shí)例化一對(duì)象時(shí)被自動(dòng)調(diào)用的,也就是說(shuō)在類(lèi)中的所有方法中只有構(gòu)造方法是被優(yōu)先調(diào)用的,所以使用this調(diào)用構(gòu)造方法必須也只能放在構(gòu)造方法的第一行。下面的程序就是一個(gè)錯(cuò)誤的程序。 5.10static關(guān)鍵字的使用
5.10.1靜態(tài)變量
在程序中如果用static聲明變量,則此變量稱(chēng)為靜態(tài)變量。那么什么是靜態(tài)變量呢?使用靜態(tài)變量又有什么好處呢?
【例5-25】TestStaticDemo1.java。輸出結(jié)果:
我是:張三,今年:25歲,來(lái)自:中國(guó)
我是:李四,今年:30歲,來(lái)自:中國(guó)
我是:王五,今年:35歲,來(lái)自:中國(guó)
程序說(shuō)明:
(1)第1~16行聲明一個(gè)名為Person的類(lèi),含有三個(gè)屬性:name、age、city。
(2)第6~11行聲明Person類(lèi)的一個(gè)構(gòu)造方法,此構(gòu)造方法分別為各屬性賦值。
(3)第12~15行聲明一個(gè)talk()方法,此方法用于返回用戶信息。
(4)第21~23行分別實(shí)例化三個(gè)Person對(duì)象。
(5)第24~26行分別調(diào)用類(lèi)中的talk()方法輸出用戶信息。
由上面的程序可以發(fā)現(xiàn),所有的Person對(duì)象都有一個(gè)city屬性,而且所有的屬性也全部相同,如圖5-12所示。圖5-12static變量?jī)?nèi)存示意圖讀者可以試著想一想,現(xiàn)在假設(shè)程序產(chǎn)生了50個(gè)Person對(duì)象,如果想修改所有人的city屬性,那么是否就要調(diào)用50遍city屬性進(jìn)行重新修改呢?顯然這樣太麻煩了。在Java中提供了static關(guān)鍵字,用它來(lái)修飾類(lèi)的屬性后,則此屬性就是公共屬性。將TestStaticDemo1.java程序稍作修改就形成了TestStaticDemo2.java,如下所示。
【例5-26】TestStaticDemo2.java。程序說(shuō)明:
(1)第1~15行聲明一個(gè)名為Person的類(lèi),含有三個(gè)屬性:name、age、city。其中,city為static類(lèi)型
(2)第6~10行聲明Person類(lèi)的一個(gè)構(gòu)造方法,此構(gòu)造方法的作用是分別為name、age屬性賦值。
(3)第11~14行聲明一個(gè)talk()方法,此方法用于返回用戶信息。
(4)第20~22行分別實(shí)例化三個(gè)Person對(duì)象。
(5)第23~25行分別調(diào)用類(lèi)中的talk()方法,輸出用戶信息。
(6)第28行修改了p1中的city屬性。從上面的程序中可以發(fā)現(xiàn),程序只在第28行修改了city屬性,而且只修改了一個(gè)對(duì)象的city屬性,但再次輸出時(shí),發(fā)現(xiàn)全部對(duì)象的city值都發(fā)生了一樣的變化,這就說(shuō)明了用static聲明的屬性是所有對(duì)象共享的,如圖5-13所示。圖5-13static變量的使用從圖5-13中可以看出,所有的對(duì)象都指向同一個(gè)city屬性,只要其中有一個(gè)對(duì)象修改了city屬性的內(nèi)容,則所有對(duì)象都會(huì)被同時(shí)修改。
另外,需要注意一點(diǎn),用static方式聲明的屬性也可以用類(lèi)名直接訪問(wèn)。例如,要想修改city屬性中的內(nèi)容,則可以用如下方式:
Person.city="美國(guó)";
所以有些書(shū)上也把用static類(lèi)型聲明的變量稱(chēng)為“類(lèi)變量”。既然static類(lèi)型聲明的變量是所有對(duì)象共享的內(nèi)存空間,也就是說(shuō)無(wú)論最終有多少個(gè)對(duì)象產(chǎn)生,也都只有一個(gè)static類(lèi)型的屬性,那么可不可以用它來(lái)計(jì)算類(lèi)到底產(chǎn)生了多少個(gè)實(shí)例對(duì)象呢?讀者可以想一想,只要一個(gè)類(lèi)產(chǎn)生一個(gè)新的實(shí)例對(duì)象,就都會(huì)去調(diào)用構(gòu)造方法,所以可以在構(gòu)造方法中加入一些計(jì)數(shù)操作,如下面的程序:5.10.2靜態(tài)方法
static既可以在聲明變量時(shí)使用,也可以用其來(lái)聲明方法。用它聲明的方法有時(shí)被稱(chēng)為“類(lèi)方法”。
【例5-27】TestStaticDemo4.java。程序說(shuō)明:
(1)第1~19行聲明一個(gè)名為Person的類(lèi),類(lèi)中含有一個(gè)static類(lèi)型的變量city,并對(duì)此對(duì)象進(jìn)行了封裝。
(2)第15~18行聲明一個(gè)static類(lèi)型的方法,此方法也可以用類(lèi)名直接調(diào)用,用于修改city屬性的內(nèi)容。
(3)第32行由Person調(diào)用setCity()方法,對(duì)city的內(nèi)容進(jìn)行修改。
在使用static類(lèi)型聲明方法時(shí)需要注意的是,如果在類(lèi)中聲明了一個(gè)static類(lèi)型的屬性,則此屬性既可以在非static類(lèi)型的方法中使用,也可以在static類(lèi)型的方法中使用。但用static類(lèi)型的屬性調(diào)用非static類(lèi)型的屬性時(shí),會(huì)出現(xiàn)錯(cuò)誤。
【例5-28】PersonStatic.java。5.10.3main()方法
在前面的章節(jié)中已經(jīng)介紹,如果一個(gè)類(lèi)要被Java解釋器直接裝載運(yùn)行,那么這個(gè)類(lèi)中必須有main()方法。
由于Java虛擬機(jī)需要調(diào)用類(lèi)的main()方法,所以該方法的訪問(wèn)權(quán)限必須是public,又因?yàn)镴ava虛擬機(jī)在執(zhí)行main()方法時(shí)不必創(chuàng)建對(duì)象,所以該方法必須是static的。該方法接收一個(gè)String類(lèi)型的數(shù)組參數(shù),該數(shù)組中保存執(zhí)行Java命令時(shí)傳遞給所運(yùn)行的類(lèi)的參數(shù)。
向Java中傳遞參數(shù)可用如下命令:
java類(lèi)名稱(chēng)參數(shù)1參數(shù)2參數(shù)3
通過(guò)運(yùn)行下面的程序可了解如何向類(lèi)中傳遞參數(shù)以及程序又是如何取得這些參數(shù)的。
【例5-29】TestMain.java。運(yùn)行程序:
javaTestMainfirstsecond
輸出結(jié)果:
first
second
程序說(shuō)明:
(1)程序第14行判斷輸入?yún)?shù)的個(gè)數(shù)是否為兩個(gè)參數(shù),如果不是,則退出程序。
(2)所有接收的參數(shù)都被存放在args[]字符串?dāng)?shù)組中,用for循環(huán)輸出全部?jī)?nèi)容。5.10.4靜態(tài)代碼塊
一個(gè)類(lèi)可以使用不包含在任何方法體中的靜態(tài)代碼塊,當(dāng)類(lèi)被載入時(shí),靜態(tài)代碼塊被執(zhí)行,且只執(zhí)行一次。靜態(tài)代碼塊經(jīng)常用來(lái)進(jìn)行類(lèi)屬性的初始化。
【例5-30】TestStaticDemo5.java。程序說(shuō)明:
(1)第1~12行聲明一個(gè)名為Person的類(lèi)。
(2)第8~11行聲明一個(gè)靜態(tài)代碼塊,此代碼塊放在Person類(lèi)中。
(3)第15~18行在類(lèi)TestStaticDemo5中也聲明一靜態(tài)代碼塊。
(4)第22、23行分別產(chǎn)生了兩個(gè)Person類(lèi)的匿名對(duì)象。
從程序運(yùn)行結(jié)果中可以看出,放在TestStaticDemo5類(lèi)中的靜態(tài)代碼塊首先被調(diào)用,這是因?yàn)槌绦蚴紫葓?zhí)行TestStaticDemo5類(lèi),所以此程序的靜態(tài)代碼塊會(huì)首先被執(zhí)行。程序在22、23行產(chǎn)生了兩個(gè)匿名對(duì)象,Person類(lèi)中的靜態(tài)代碼塊只執(zhí)行了一次,而且靜態(tài)代碼塊優(yōu)先于靜態(tài)方法,由此可以發(fā)現(xiàn),靜態(tài)代碼塊可以為靜態(tài)屬性初始化。案例2static成員變量和實(shí)例變量的區(qū)別
【案例描述】
用程序模擬趙莊和李莊兩個(gè)村莊,這兩個(gè)村莊共用一口水井。
【代碼與注釋】 5.11構(gòu)造方法的私有
方法依實(shí)際需要,可分為public與private。同樣地,構(gòu)造方法也有public與private之分。到目前為止,所使用的構(gòu)造方法均屬于public,它可以在程序的任何
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 電信課程設(shè)計(jì)案例
- 總賬初始化設(shè)置課程設(shè)計(jì)
- 小學(xué)生外國(guó)傳統(tǒng)課程設(shè)計(jì)
- 2024年黑龍江省安全員C證考試題庫(kù)
- 系統(tǒng)soc課程設(shè)計(jì)
- 磚混廠房概預(yù)算課程設(shè)計(jì)
- 穩(wěn)壓電流源課程設(shè)計(jì)
- 籃球暑期課程設(shè)計(jì)意圖
- 研學(xué)課程設(shè)計(jì)南鑼鼓巷
- 糖化熱量衡算課程設(shè)計(jì)
- 湖南2025年湖南機(jī)電職業(yè)技術(shù)學(xué)院合同制教師招聘31人歷年參考題庫(kù)(頻考版)含答案解析
- 2024年電子交易:電腦買(mǎi)賣(mài)合同
- 中國(guó)文化概論知識(shí)試題與答案版
- 期末復(fù)習(xí)提升測(cè)試(試題)(含答案)2024-2025學(xué)年四年級(jí)上冊(cè)數(shù)學(xué)人教版
- 生和碼頭港口設(shè)施維護(hù)管理制度(3篇)
- 黑龍江省哈爾濱市第六中學(xué)2025屆高考數(shù)學(xué)三模試卷含解析
- 傷口治療師進(jìn)修匯報(bào)
- 研學(xué)活動(dòng)協(xié)議書(shū)合同范本
- ISBAR輔助工具在交班中應(yīng)用
- AIGC行業(yè)報(bào)告:國(guó)內(nèi)外大模型和AI應(yīng)用梳理
- 換熱器的原理及構(gòu)造
評(píng)論
0/150
提交評(píng)論