




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第3章Java面向?qū)ο缶幊堂嫦驅(qū)ο蟮能浖_發(fā)和相應(yīng)的面向?qū)ο蟮某绦蛟O(shè)計方法是當(dāng)今計算機(jī)技術(shù)發(fā)展的重要成果和趨勢之一。Java是一種完全面向?qū)ο蟮某绦蛟O(shè)計語言,它的所有數(shù)據(jù)類型和函數(shù)都封裝在類中。Java所實現(xiàn)的封裝、繼承、多態(tài)性等面向?qū)ο蟮膶傩裕档土顺绦虻膹?fù)雜性,實現(xiàn)了代碼的可重用性,提高了運行效率,使Java不依賴于機(jī)器的結(jié)構(gòu),具有平臺無關(guān)性、分布式、可移植性、可重用性、健壯性、安全性等特點。3.1面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ)3.2類與對象3.3成員變量和成員方法的定義與實現(xiàn)3.4類的繼承與多態(tài)3.5包3.6接口和內(nèi)部類習(xí)題第3章Java面向?qū)ο缶幊堂嫦驅(qū)ο蟮能浖_發(fā)和相應(yīng)的面學(xué)習(xí)目標(biāo)
【學(xué)習(xí)目標(biāo)】了解面向?qū)ο缶幊痰幕纠碚摵突靖拍睿莆彰嫦驅(qū)ο缶幊痰幕痉椒?,學(xué)習(xí)后能夠編寫體現(xiàn)OOP風(fēng)格的Java程序?!颈菊轮R點】類和對象的概念面向?qū)ο蟮奶匦灶愖兞亢皖惙椒ǖ氖褂梅庋b和修飾符的使用內(nèi)部類的使用接口的使用包層次的理解和使用學(xué)習(xí)目標(biāo)【學(xué)習(xí)目標(biāo)】3.1面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ)3.1.1面向?qū)ο蟾攀?.1.2面向?qū)ο笾械幕靖拍?.1.3面向?qū)ο蟪绦蛟O(shè)計方法的優(yōu)點3.1面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ)3.1.1面向?qū)ο蟾攀?.1.1面向?qū)ο蟾攀鲈缙谟嬎銠C(jī)中運行的程序大都是為特定的硬件系統(tǒng)專門設(shè)計的,稱為面向機(jī)器的程序。這類程序的運行速度和效率都很高,但是可讀性和可移植性很差,隨著軟件開發(fā)規(guī)模的擴(kuò)大,這類面向機(jī)器的程序逐漸被以C為代表的面向過程的程序所取代。面向過程問題求解的核心組成是數(shù)據(jù)結(jié)構(gòu)和算法。其中數(shù)據(jù)結(jié)構(gòu)利用計算機(jī)的離散邏輯來量化表達(dá)需要解決的問題,而算法則研究如何快捷、高效地組織解決問題的具體過程。面向過程的程序設(shè)計是以具體的的解體過程為研究和實現(xiàn)的主體,可以精確、完備地描述具體的求解過程(這里的過程通常是指操作),但卻不足以把一個包含了多個相互關(guān)聯(lián)的過程的復(fù)雜系統(tǒng)表述清楚。面向?qū)ο蟮某绦蛟O(shè)計不僅關(guān)心孤立的單個過程,還關(guān)心包含這些過程的復(fù)雜系統(tǒng),它能夠使計算機(jī)邏輯來模擬描述系統(tǒng)本身,包括系統(tǒng)的組成、系統(tǒng)的各種可能狀態(tài),以及系統(tǒng)中可能產(chǎn)生的各種過程與過程引起的系統(tǒng)狀態(tài)切換。3.1.1面向?qū)ο蟾攀鲈缙谟嬎銠C(jī)中運行的程序大都是為特定3.1.2面向?qū)ο笾械幕靖拍?.類與對象對象的概念是面向?qū)ο蠹夹g(shù)的核心所在。實際生活中,我們每時每刻都與“對象”打交道,比如屋頂上的貓、學(xué)生用的課桌、老王的彩色電視機(jī)等,甚至我們自己本身也是一個對象。我們平時怎樣稱呼對象呢?我們會以這個對象分類的名稱來稱呼它,例如城市里有很多貓、大街上有很多車、我要去看電視等等,這里的貓、車、課桌、電視都只是對象的一種分類而已。在Java中,我們稱之為類。面向?qū)ο蠹夹g(shù)中另一個重要概念就是類,類是模板也是藍(lán)圖,從類中構(gòu)造一個對象,即創(chuàng)建了一個類的實例。類好比一個建材市場,其中有許多子類——各種各樣的裝飾材料,而我們裝修自己的房子就要選擇我們需要的材料(為了建立我們自己的程序,我們必須選
擇我們需要的類)。3.1.2面向?qū)ο笾械幕靖拍?.類與對象3.1.2面向?qū)ο笾械幕靖拍顚ο蠛皖愔g是什么關(guān)系呢?比如你要買一臺電視機(jī),這里的“電視機(jī)”只是個類的名稱,而你買回家的是電視機(jī)的一個實例對象,而不是一個類。所以類是一個抽象的概念,而對象是看得到、聽得見、摸得著的實例。在面向?qū)ο蟮某绦蛟O(shè)計中,將數(shù)據(jù)與對數(shù)據(jù)進(jìn)行的操作合起來定義為類。類是用來定義一組對象共同具有的狀態(tài)和行為的模板。類(Class)是一種復(fù)雜的數(shù)據(jù)類型,它是將數(shù)據(jù)和與數(shù)據(jù)相關(guān)的操作封裝在一起的集合體。類是普通數(shù)據(jù)類型的擴(kuò)展,它不但包含數(shù)據(jù),還包含了對數(shù)據(jù)進(jìn)行操作的方法(method)。方法反映的是數(shù)據(jù)的行為而不是數(shù)據(jù)本身。對象(Object)是類的實例,它是類的變量。當(dāng)程序運行時,對象占用內(nèi)存單元。對象與類是密切相關(guān)的,沒有脫離對象的類,也沒有不依賴于類的對象。3.1.2面向?qū)ο笾械幕靖拍顚ο蠛皖愔g是什么關(guān)系呢?3.1.2面向?qū)ο笾械幕靖拍顖D3-1表示了類、對象、實體的相互關(guān)系和面向?qū)ο髥栴}求解的思維方式。使用面向?qū)ο蟮姆椒ń鉀Q現(xiàn)實世界的問題時,首先將物理存在的實體抽象成概念世界的抽象數(shù)據(jù)類型,這個抽象數(shù)據(jù)類型里面包括了實體中與需要解決的問題相關(guān)的數(shù)據(jù)和屬性;然后再用面向?qū)ο蟮墓ぞ?,如Java語言,將這個抽象數(shù)據(jù)類型用計算機(jī)邏輯表達(dá)出來,即構(gòu)造計算機(jī)能夠理解和處理的類;最后將類實例化就得到了現(xiàn)實世界實體的面向?qū)ο蟮挠成洹獙ο?,在程序中對對象進(jìn)行操作,就可以模擬現(xiàn)實世界中的實體上的問題并解決之。3.1.2面向?qū)ο笾械幕靖拍顖D3-1表示了類、對象、實3.1.2面向?qū)ο笾械幕靖拍頙ava中的所有數(shù)據(jù)類型都是用類實現(xiàn)的,Java語言是建立在類這個邏輯結(jié)構(gòu)之上的,所以Java是一種完全面向?qū)ο蟮某绦蛟O(shè)計語言,而我們編寫Java程序,主要工作是編寫一個個類,然后由類生成對象,實現(xiàn)所需要的功能。映射對象類實體抽象數(shù)據(jù)類計算機(jī)邏輯的實現(xiàn)概念世界計算機(jī)世界現(xiàn)實世界抽象實例化抽象圖3-1對象、實體與類3.1.2面向?qū)ο笾械幕靖拍頙ava中的所有數(shù)據(jù)類型都3.1.2面向?qū)ο笾械幕靖拍?.成員在Java語言中,一切事物都是對象。實際上,對于每個對象都有一個抽象過程。所謂抽象,就是選取所描述事物在現(xiàn)實世界中相關(guān)特征的過程。任何事物一定存在3類信息:屬性信息:靜態(tài)刻畫對象特征。操作信息:動態(tài)刻畫對象特征。約束信息:描述對象可以存在的狀態(tài)為了使得計算機(jī)能夠處理客觀事物,必須對事物進(jìn)行抽象。在事物抽象過程中,必須胡略那些抽象事物與當(dāng)前目的無關(guān)的特征,只需要關(guān)注與當(dāng)前需求有直接影響的因素。3.1.2面向?qū)ο笾械幕靖拍?.成員3.1.2面向?qū)ο笾械幕靖拍罾?,“人”可以看作一個抽象的類,我們每一個人都是“人”類的一個實例對象。公安機(jī)關(guān)要了解某一個人的情況,目前所關(guān)注的屬性有身份證號、姓名、性別、出生日期等。而身高、體重是目前不關(guān)心的信息,要盡量去掉,當(dāng)然以后可以根據(jù)需要隨時再增加進(jìn)來。所以有了屬性,世界上每個對象都不同,就算是雙胞胎,也有不同的地方。每個對象有自己的行為或方法,比如我們可以說“那個人在吃飯”,那么吃飯、走路、工作是描述該實例的行為;又比如每臺電視都不同,但每臺電視一定會有開關(guān)機(jī)、選臺、音量調(diào)節(jié)等操作的方法,這些都屬于操作信息。我們把屬性和方法稱為這個對象的成員。類中的數(shù)據(jù)稱為成員字段(field),對數(shù)據(jù)進(jìn)行的操作稱為成員方法(method)。注意:字段表示的是類的屬性,在Java中其實就是個變量,可以按照一般變量聲明的格式進(jìn)行聲明,所以在下文中將字段稱為變量。3.1.2面向?qū)ο笾械幕靖拍罾纾叭恕笨梢钥醋饕粋€抽3.1.2面向?qū)ο笾械幕靖拍?.類的三個核心特性:封裝、繼承、多態(tài)(1)封裝封裝(encapsulation),即信息隱藏,是面向?qū)ο蟪绦蛟O(shè)計中一個非常重要的概念。封裝的目的有:隱藏類的實現(xiàn)細(xì)節(jié),以防別人誤用。迫使用戶通過接口去訪問數(shù)據(jù)。增強(qiáng)代碼的可維護(hù)性。類封裝的概念可以用集成電路芯片作類比。一塊集成電路芯片由陶瓷封裝起來,其內(nèi)部電路是不可見的,也是使用者不關(guān)心的。芯片的使用者只關(guān)心芯片的引腳的個數(shù)、引腳的電量參數(shù)以及引腳提供的功能,通過這些引腳,硬件工程師對這個芯片有了全面的了解。硬件工程師將不同芯片的引腳連在一起,就可以組成一個具有一定功能的產(chǎn)品。軟件工程師通過使用類也可達(dá)到這個目的。3.1.2面向?qū)ο笾械幕靖拍?.類的三個核心特性:封裝3.1.2面向?qū)ο笾械幕靖拍睿?)繼承繼承是一種由已有類創(chuàng)建新類的機(jī)制。為什么要使用繼承技術(shù)呢?在編寫大型應(yīng)用程序時,如果所定義的類已被使用,應(yīng)如何增加程序的可維護(hù)性?既要保證程序修改后不影響使用,又要能夠?qū)Τ绦蚬δ苓M(jìn)行不斷的補(bǔ)充。有兩種傳統(tǒng)的解決辦法:直接對原代碼進(jìn)行改動:可行,但會對現(xiàn)有使用的其它類造成影響。對原類定義進(jìn)行復(fù)制,對復(fù)制的類進(jìn)行改動,以支持新功能。此方法可行,但也會產(chǎn)生問題:在復(fù)制代碼的同時,也會復(fù)制錯誤,使得程序的可移植性和重用性差,必然導(dǎo)致工作量的增加。這兩種辦法并不能最終解決問題,更好的解決辦法是使用繼承技術(shù)。繼承機(jī)制提供了一種無限重復(fù)利用程序資源的途徑。通過繼承可以擴(kuò)充舊的程序以適應(yīng)新的需求,這樣不僅節(jié)省程序開發(fā)時間,而且為未來程序設(shè)計增添了新的資源。3.1.2面向?qū)ο笾械幕靖拍睿?)繼承3.1.2面向?qū)ο笾械幕靖拍睿?)多態(tài)一般來講,多態(tài)就是多種形態(tài)的意思。我們已經(jīng)知道,利用面向?qū)ο蟮恼Z言編程,主要工作是編寫一個個類,每一個類中可能有多個成員方法,這些方法各自對應(yīng)一定的功能,它們之間是不能重名的,否則在用名字調(diào)用時,就會產(chǎn)生歧義和錯誤。但在實際編程過程中,有時卻需要利用這樣的“重名”現(xiàn)象來提高程序的抽象度和簡潔性,這就體現(xiàn)了多態(tài)性。所謂多態(tài),是指一個程序中使用相同名字的定義了不同的方法。多態(tài)性允許以統(tǒng)一的風(fēng)格處理已存在的變量及相關(guān)的類。多態(tài)性使得向系統(tǒng)增加新功能變得容易。繼承性和多態(tài)性是降低軟件復(fù)雜性的有效技術(shù)。3.1.2面向?qū)ο笾械幕靖拍睿?)多態(tài)3.1.3面向?qū)ο蟪绦蛟O(shè)計方法的優(yōu)點相對于傳統(tǒng)的面向過程的程序設(shè)計,面向過程的程序設(shè)計更符合人解決問題的思維習(xí)慣,它具有如下優(yōu)點:1.對象的數(shù)據(jù)封裝特性徹底消除了傳統(tǒng)結(jié)構(gòu)方法中數(shù)據(jù)與操作分離所帶來的種種問題,提高了程序的可重用性和可維護(hù)性,降低了程序員保持?jǐn)?shù)據(jù)與操作相容的負(fù)擔(dān)。2.對象的數(shù)據(jù)封裝特性還可以把對象的私有數(shù)據(jù)和公共數(shù)據(jù)分離開,保護(hù)了私有數(shù)據(jù),減少了可能的模塊間干擾,達(dá)到降低程序復(fù)雜性、提高可控制性的目的。3.通過繼承和多態(tài),可以很方便地實現(xiàn)應(yīng)用的擴(kuò)展和已有代碼的重復(fù)使用,在保證質(zhì)量的前提下提高了開發(fā)效率,減小軟件修改的難度。3.1.3面向?qū)ο蟪绦蛟O(shè)計方法的優(yōu)點相對于傳統(tǒng)的面向過程3.2類與對象3.2.1類的聲明、類體3.2.2創(chuàng)建對象與構(gòu)造方法3.2類與對象3.2.1類的聲明、類體3.2.1類的聲明、類體
成員變量的聲明格式:[<修飾符>][static][final][transient]<變量類型><變量名>;其中,方括號中的項都是可選的。各項的含義如下:static指明變量是一個類成員變量。final指明變量是常量。transient指明變量是臨時變量。如:例類的聲明、類體
成員變量的聲明格式:3.2.2創(chuàng)建對象與構(gòu)造方法類的行為由它的方法實現(xiàn),其他對象可以調(diào)用對象的方法來得到該對象的服務(wù)。方法的聲明與實現(xiàn)也可分為兩部分:方法聲明和方法體。成員方法的聲明格式:[修飾符]<返回值類型><方法名>([參數(shù)列表])[throws<異常類>]{<方法體>}如:例3.6
3.2.2創(chuàng)建對象與構(gòu)造方法類的行為由它的方法實現(xiàn),其他3.3.3類的封裝前面我們設(shè)計的所有Person類,其中age屬性是其他所有類都能直接使用或是修改的,這樣的使用方式雖然很直接也很簡單,不過有一個很嚴(yán)重的問題。age屬性是一個int類型的變量,它的取值范圍很大,你可以把它設(shè)為-12,也可以把它設(shè)為10000,可是世界上沒有一個人的年齡為負(fù)數(shù),也沒有一個人活了10000歲。所以我們必須保護(hù)這種屬性,防止別人亂用。保護(hù)的方式就是把屬性隱藏起來,使得其他類只有通過特定的方法才能使用、修改這些屬性。在面向?qū)ο蟪绦蛟O(shè)計中,信息的隱藏就是封裝(encapsulation)。封裝的目的有:隱藏類的實現(xiàn)細(xì)節(jié),保護(hù)類中的數(shù)據(jù)不被誤用或破壞。迫使用戶通過接口去訪問數(shù)據(jù)。增強(qiáng)代碼的可維護(hù)性。3.3.3類的封裝前面我們設(shè)計的所有Person類,其中3.3.3類的封裝那么,如何封裝呢?根據(jù)封裝原則,使用者可以訪問類中的部分方法,但不能直接訪問成員變量。Java中通過設(shè)置類的訪問權(quán)限和類中成員的訪問權(quán)限,來實現(xiàn)封裝的特性。在聲明一個類時,可以不用權(quán)限修飾符,也可以用public設(shè)置類為公有的,不允許使用其他的權(quán)限修飾符。對于類中成員的訪問權(quán)限,Java定義了4種訪問權(quán)限:公有的(public)、保護(hù)的(protected)、默認(rèn)(default)的和私有的(private)。表3-1說明了每一種權(quán)限修飾符允許的訪問級別。3.3.3類的封裝那么,如何封裝呢?根據(jù)封裝原則,使用者3.3.3類的封裝權(quán)限修飾符同一類同一包不同包的子類所有類公有的(public)保護(hù)的(protected)默認(rèn)的(default)私有的(private)表3-1權(quán)限修飾符允許的訪問級別3.3.3類的封裝權(quán)限修飾符同一類同一包不同包的子類所有3.3.3類的封裝當(dāng)設(shè)置類成員的訪問權(quán)限時,4種修飾方式的含義如下:公有的(public):說明該類成員可被所有類的對象使用。保護(hù)的(protected):說明該類成員能被同一類中的其他成員、或其子類成員、或同一包中的其他類訪問,不能被其他包的非子類訪問。默認(rèn)的(default):其實并沒有一個叫default的修飾符,如果在聲明一個成員時,成員前面沒有加上其他三種修飾符,就叫default。它的限制比protected還嚴(yán)格,它使得該類成員能被同一類中的其他成員、或同一包中的其他類訪問,但不能被其他包的類訪問。私有的(private):說明該類成員只能被同一類中的其他成員訪問,不能被其他類的成員訪問,也不能被子類成員訪問。成員方法和成員變量都是Java類的成員。當(dāng)聲明一個類的成員時,可以使用權(quán)限修飾符允許或不允許其他類的對象訪問其成員。如:例類的封裝當(dāng)設(shè)置類成員的訪問權(quán)限時,4種修飾方式3.3.3類的封裝類型初值類型初值byte0float0.0fshort0double0.0int0char'\u0000'long0booleanfalse引用類型null表3-2Java各種類型變量的初值3.3.3類的封裝類型初值類型初值byte0float03.3.4實例成員和類成員以前我們看到的屬性或是方法,都是屬于對象等級的,它們是伴隨對象的,也就是說只有當(dāng)對象實例化以后,那些屬性和方法才有存在的意義,因此我們稱這些屬性或方法為實例成員。學(xué)校里人很多,為了方便管理,所以我們必須統(tǒng)計出人的總數(shù)。有些屬性和方法不需要伴隨對象,例如學(xué)校的總?cè)藬?shù),如果我們把它交由上層的類來管理,會比較容易而且效率更高,我們稱這種屬性或方法為類成員。Java類就包括兩種成員:實例成員和類成員。類成員也稱為靜態(tài)成員。使用static修飾的成員稱為類成員。3.3.4實例成員和類成員以前我們看到的屬性或是方法,都3.3.4實例成員和類成員1.實例變量和類變量類的成員變量有實例變量和類變量兩種。沒有static修飾的變量稱為實例變量,每次創(chuàng)建類的一個實例對象時,系統(tǒng)會為對象的每一個實例變量分配內(nèi)存單元。用static修飾的變量稱為類變量或靜態(tài)變量,系統(tǒng)運行時,只為該類的第一個對象分配內(nèi)存單元,其后所有新創(chuàng)建的對象都共享這一個類變量。2.實例方法和類方法類的成員變量有實例方法和類方法兩種。沒有static修飾的方法稱為實例方法。實例方法體中既可以訪問類變量,也可以訪問實例變量。實例方法只能通過對象來調(diào)用。用static修飾的方法稱為類方法或靜態(tài)方法。類方法體中只能訪問類變量。類方法既可以通過對象來調(diào)用,也可以通過類名調(diào)用。如:例實例成員和類成員1.實例變量和類變量3.3.4實例成員和類成員注釋:許多面向?qū)ο笳Z言(如C++)要求程序跟蹤所以創(chuàng)建的對象,在對象使用完后顯式地銷毀對象,用這種方式編寫管理內(nèi)存的代碼既麻煩有容易出錯。而在Java中,程序員只需創(chuàng)建對象,不需要顯式地銷毀它們。因為Java有垃圾回收機(jī)制,能自動判斷對象是否在使用,如果不使用,則自動銷毀它,收回對象所占的資源。在程序中也可以使用析構(gòu)方法finalize()隨時銷毀對象。Java的每個類都有一個析構(gòu)方法,用于將資源返回給系統(tǒng)。方法finalize()沒有參數(shù),也不返回值。3.3.4實例成員和類成員注釋:3.4類的繼承與多態(tài)3.4.1類的繼承3.4.2類的多態(tài)3.4.3最終類和抽象類3.4類的繼承與多態(tài)3.4.1類的繼承3.4.1類的繼承1.繼承的概念根據(jù)不同的職業(yè),人可以分為警察、演員等不同的類別。光靠一個Person類來包括各種職業(yè)的屬性和方法,其結(jié)構(gòu)性是很差的。所以我們必須設(shè)計新的類,來管理不同職業(yè)的人。所謂繼承(inheritance),就是一種由已有類創(chuàng)建新類的機(jī)制。利用繼承,我們可以先創(chuàng)建一個具有公共屬性的一般類,然后根據(jù)該一般類再創(chuàng)建具有特殊屬性的新類。新類繼承一般類的屬性和方法,并根據(jù)需要增加它自己的屬性和方法。由繼承而得到的新類稱為子類(subclass),被繼承的類稱為超類(supclass),也被稱為父類。3.4.1類的繼承1.繼承的概念3.4.1類的繼承例如,當(dāng)類sub1繼承類super時,就表明sub1是super的子類,super是sub1的超類,如圖3-2所示。子類從超類中繼承變量和方法,從而可以共享數(shù)據(jù)和方法。Sub1類由兩部分組成:繼承部分和增加部分。繼承部分是從super繼承過來的,把super的成員映射成sub1的繼承成員;增加部分是專為sub1編寫的新代碼。如:例3.9圖3-2繼承性注意:Java不支持多重繼承,即子類只能有一個超類。3.4.1類的繼承例如,當(dāng)類sub1繼承類super時,3.4.1類的繼承2.創(chuàng)建子類實現(xiàn)繼承在類的聲明中,通過使用關(guān)鍵字entends來創(chuàng)建一個類的子類,顯式聲明格式為:[<修飾符>]class<子類名>extends<超類名>例如,classStudentextendsPerson3.4.1類的繼承2.創(chuàng)建子類實現(xiàn)繼承3.4.1類的繼承子類繼承超類中所有可被子類訪問的成員變量。繼承原則如下:能夠繼承聲明為public和protected的成員變量。能夠繼承同一包中的那些默認(rèn)修飾符的成員變量。不能繼承聲明為private的成員變量。如果子類聲明一個與超類成員變量同名的成員變量,則不能繼承超類的成員變量。此時,子類的成員變量稱為隱藏了超類的成員變量。子類繼承方法的規(guī)則類似于繼承成員變量的規(guī)則:子類繼承超類中所有可被子類訪問的成員方法。繼承原則如下:能夠繼承聲明為public和protected的成員方法。能夠繼承同一包中的那些默認(rèn)修飾符的成員方法。不能繼承聲明為private的成員方法。不能繼承超類的構(gòu)造方法。如果子類方法與超類方法同名,則不能繼承。子類方法稱為覆蓋了超類的同名方法。3.4.1類的繼承子類繼承超類中所有可被子類訪問的成員變3.4.1類的繼承注意:Java中每個類都有超類,如果沒有顯式標(biāo)明類的超類,則隱含地假設(shè)超類為在語言包java.lang中說明的Object類。如:例類的繼承注意:3.4.1類的繼承歸納注釋:繼承是軟件重用的一種形式,也是自動地實現(xiàn)類中方法和數(shù)據(jù)共享的機(jī)制。如果沒有繼承機(jī)制,那么一個系統(tǒng)中的類是封閉的、相互無關(guān)的。多個類實現(xiàn)相似的功能勢必造成數(shù)據(jù)和方法的大量重復(fù)。而有了繼承機(jī)制,多個類就可以相互關(guān)聯(lián),新類從已存在的類中產(chǎn)生,通過保留它們的屬性和方法實現(xiàn)代碼重用,又可以根據(jù)新類的要求添加新的屬性和方法,以支持新功能。在編寫大型應(yīng)用程序時,軟件重用可大大縮短軟件開發(fā)時間,提高系統(tǒng)性能,減少系統(tǒng)在使用過程中出現(xiàn)的問題。3.4.1類的繼承歸納注釋:3.4.2類的多態(tài)所謂多態(tài)(polymorphism),是指一個名字可具有多種語義,即“同名異示”。例如,我們經(jīng)常說,“哺乳動物有很多種叫聲”,描述為“吼”、“嚎”、“汪汪”、“喵喵”等,這就是叫聲的多態(tài)。如何實現(xiàn)叫聲的多態(tài)呢?我們寫動物類時,寫了“叫聲”方法,動物類有很多子類,并且這些子類都重寫了超類中的“叫聲”方法,會產(chǎn)生不同的行為。比如,狗類對象調(diào)用“叫聲”方法時,產(chǎn)生的行為是“汪汪”,而貓類對象調(diào)用“叫聲”方法時,產(chǎn)生的行為是“喵喵”。這就實現(xiàn)了叫聲的多態(tài)。多態(tài)性允許以統(tǒng)一的風(fēng)格處理已存在的變量及相關(guān)的類。多態(tài)性使得向系統(tǒng)增加新功能變得容易。繼承和多態(tài)是降低軟件復(fù)雜性的有效技術(shù)。通常有兩種途徑實現(xiàn)多態(tài):方法的重載和覆蓋。3.4.2類的多態(tài)所謂多態(tài)(polymorphism),3.4.1類的繼承1.方法的重載所謂方法的重載(methodoverloading),是指一個類中有許多同名的方法帶有不同的參數(shù)表。方法重載時,要求:參數(shù)必須不同,即可以是參數(shù)個數(shù)不同,也可以是個數(shù)相同而類型不同。返回值可以相同,也可以不同。例如,輸出語句print的參數(shù)可以是Java中的任何基本類型,其實就是對print()方法的重載:publicvoidprint(booleanb)publicvoidprint(charc)publicvoidprint(inti)publicvoidprint(longl)publicvoidprint(floatf)publicvoidprint(doubled)例3.11構(gòu)造方法的重載3.4.1類的繼承1.方法的重載3.4.1類的繼承歸納注釋:重載的價值在于它允許通過使用一個普通的方法名來訪問一系列相關(guān)的方法。當(dāng)調(diào)用一個方法時,具體執(zhí)行哪一個方法要根據(jù)調(diào)用方法的參數(shù)決定,Java運行系統(tǒng)僅執(zhí)行與調(diào)用的參數(shù)相匹配的重載方法。盡管Java并沒有規(guī)定重載方法之間必須有聯(lián)系,但習(xí)慣上,為了使程序容易讀懂,最好重載相同含義的方法。3.4.1類的繼承歸納注釋:3.4.1類的繼承2.方法的覆蓋在有繼承關(guān)系的兩個類中,如果子類方法與超類方法同名,則該方法不能繼承,此時子類的方法稱為覆蓋(override)了超類中的同名方法。例如,在例3.10中,三個子類Student_i、Professor_i、Assistant_i類都繼承超類Person_i,子類中都重寫work方法覆蓋了超類中的同名方法,各個子類的work方法彼此不同,都實現(xiàn)了與超類不同的行為。特別是在程序中第80行,子類Assistant_i中重寫work方法覆蓋了超類中的同名方法,在89行子類對象a調(diào)用的work方法是子類的,所以輸出了語句“Talkingwithastudent”,而不是超類的work方法中要輸出的“Working...”。所以,方法的覆蓋與類的繼承有密切的關(guān)系。覆蓋體現(xiàn)了子類補(bǔ)充或改變超類方法的能力。通過覆蓋使一個方法在不同的子類間表現(xiàn)出不同的行為。3.4.1類的繼承2.方法的覆蓋3.4.1類的繼承在進(jìn)行覆蓋時,應(yīng)注意以下三點:子類不能覆蓋超類中聲明為final或static的方法。子類必須覆蓋超類中聲明為abstract的方法,或者子類也聲明為abstract。子類覆蓋超類中同名方法時,子類方法聲明必須與超類被覆蓋方法的聲明一樣。3.4.1類的繼承在進(jìn)行覆蓋時,應(yīng)注意以下三點:3.4.3最終類和抽象類1.最終類最終類是指不能被繼承的類,即:最終類不能有子類。如果不希望某個類被繼承,可以用關(guān)鍵字final來聲明這個類為最終類。例如:finalclassC//合法,C為最終類classLxextendsC//非法,Lx不能為最終類的子類如果想保護(hù)類中的方法不被子類覆蓋,可以在聲明中用關(guān)鍵字final來聲明這個方法為最終方法。例如:finalvoidm();//合法,m為最終方法2.抽象類為了確保一個方法能被子類的方法覆蓋,則使用關(guān)鍵字abstract聲明該方法為抽象方法。例如:3.4.3最終類和抽象類1.最終類3.4.3最終類和抽象類abstractclassD//合法,D為抽象類classLxextendsD//合法,Lx可以為抽象類的子類Dd=newD()//非法,抽象類不能實例化抽象類的子類必須實現(xiàn)超類中的所以抽象方法,或者將自己也聲明為抽象的。一個類不能既是最終類,又是抽象類,即:關(guān)鍵字final和abstract不能合用。當(dāng)我們定義一個抽象概念時,可以聲明一個抽象類只描述其中的結(jié)構(gòu),而不實現(xiàn)每個方法。這個抽象類可以作為一個超類被它的所有子類所共享,而其中的方法由每個子類去實現(xiàn)具體細(xì)節(jié)。3.4.3最終類和抽象類abstractclassD3.5包3.5.1包的概念3.5.2引用Java定義的包3.5包3.5.1包的概念3.5.1包的概念
Java允許使用包(package)把類聚集起來。所以包是一種區(qū)別類名空間的機(jī)制,是類的組織方式,包對應(yīng)一個文件夾,包中還可以再有子包,稱為包等級。為什么要使用包呢?假設(shè)有兩個程序員不約而同地提供了Student類,只要他們把自己的類放入不同的包中,那么就不會產(chǎn)生沖突。對于其中不同的項目,則使用子包進(jìn)行區(qū)分。包等級的唯一目的是要管理唯一的名字。從編譯器的角度來看,包和其中的子包沒有任何關(guān)系。例如,包java.util和java.util.jar就是彼此無關(guān)的,它們每一個都有自己獨立的類集合。3.5.1包的概念
Java允許使用包(package)3.5.2引用Java定義的包在本書第1章有關(guān)Java的API結(jié)構(gòu)的內(nèi)容中,對Java的常用包作了簡單介紹,在此不再贅述。為能使用其他包中的類(或接口),在Java語言中提供了一個包可以使用另一個包中類(或接口)的定義和實現(xiàn)的機(jī)制。在一個包中的類共有兩種方式定義來自其他包中的類(或接口)。1.前綴包名法在每個欲引用的類(或接口)名前簡單加上完整的包名。例如,java.util.Datetoday=newjava.util.Date();顯然,這樣太繁瑣。3.5.2引用Java定義的包在本書第1章有關(guān)Java的3.5.2引用Java定義的包2.使用import關(guān)鍵詞在源程序中使用import語句導(dǎo)入Java包中的一個類(或接口),或者包含它們的包。導(dǎo)入一個包后,該包所有的公用類和接口均可使用。import語句的格式為:import<包名1>[.<包名2>[.<包名3>···]].<類名>|*;其中import為關(guān)鍵字,多個包名及類名之間用圓點分隔,“*”表示包中的所有類。import語句可以有多個,但必須都在文件頂部package語句后,并且在文件中第一個類或接口定義之前。例如,先有語句importjava.util.*; 然后,可以直接使用下面的語句:Datetoday=newDate();如果存在名字沖突,必須使用前綴包名法。例如:importjava.util.*;importjava.sql.*;……//其他語句Datetoday=newDate();3.5.2引用Java定義的包2.使用import關(guān)鍵詞3.5.2引用Java定義的包該程序在編譯時會報錯,因為java.util包和java.sql包中都有Date類,編譯器無法確定用哪一個類創(chuàng)建對象today。改為下面的代碼就可編譯通過:importjava.util.*;importjava.sql.*;java.util.Datetoday=newjava.util.Date();java.sql.Dateyesterday=newjava.sql.Date();3.設(shè)置包的路徑要引用Java包,僅在源碼中增加import語句是不夠的,還必須告訴系統(tǒng),程序運行時到哪里才能找到Java的包。這個功能由環(huán)境變量classpath完成。在本書第1章JDK的安裝過程中已經(jīng)有關(guān)于如何設(shè)置環(huán)境變量classpath的內(nèi)容:setclasspath=.;C:\ProgramFiles\Java\jdk1.5.0_07\lib如:例引用Java定義的包該程序在編譯時會報錯,因為3.5.3自定義包除了可以引用Java定義的包之外,程序員還可以定義自己的包。1.包的定義格式(1)包的定義格式如下:Package<包名>;其中,package是關(guān)鍵字,<包名>是標(biāo)示符。例如:Packageschool;PublicclassPerson_i;(2)包等級的定義格式如下:Package<包名1>[.<包名2>[.<包名3>]];用圓點“.”將每個包名分隔就能形成包等級,而包等級中的包名稱說明Java類的命名空間的目錄層次。例如:Packageschool.one.two;同時要求one是school的子文件夾,而two是one的子文件夾。要注意的是,如果改變某一個包名,必須同時改變對應(yīng)的文件夾名。因為包的名字與類存放的文件夾同名。3.5.3自定義包除了可以引用Java定義的包之外,程序3.5.3自定義包2.設(shè)置包的路徑對于程序員自定義的包school,系統(tǒng)如何知道這個包在哪里?其他類如何引用他?我們在D:\myjava之中創(chuàng)建一個與包同名的文件夾D:\myjava\school,并將編譯過的文件(Person_i.class)放入該文件夾中。注意:該包名與文件夾名應(yīng)該一致。添加環(huán)境變量classpath的路徑如下:setclasspath=.;C:\jdk1.3.0_02\lib;D:\myjava其他類用importschool.*;語句可以引用school包中的類。程序運行時,系統(tǒng)將在D:\myjava中尋找school包。JVM在定位一個Java類文件時分為兩個步驟:外部定位:根據(jù)classpath環(huán)境變量定位查找Java類的起始位置。內(nèi)部定位:根據(jù)每個Java類中package關(guān)鍵字所定義層次在Java命名空間中進(jìn)行再定位。3.5.3自定義包2.設(shè)置包的路徑3.5.3自定義包例3.13包等級的創(chuàng)建及使用。按照下列目錄結(jié)構(gòu),改寫例3.9和例3.10中的4個類Person_i、Student_i、Professor_i、Assistant_i,把類添加到相應(yīng)的包中。設(shè)計一個信息系學(xué)生的新類Is,使之繼承Student_i類,并在Is中創(chuàng)建包中所有類的對象且調(diào)用各個類的move方法。目錄結(jié)構(gòu)為:D:\myjava\schoolPerson_i.javamanagement\Assistant_i.javaAssistant_i.classstudent\Student_i.javaStudent_i.classIs.javaIs.classteacher\Professor_i.javaProfessor_i.class3.5.3自定義包例3.13包等級的創(chuàng)建及使用。3.5.3自定義包(1)設(shè)置classpathsetclasspath=.;C:\ProgramFiles\Java\jdk1.5.0\lib;D:\myjava(2)修改并編譯原有的四個類首先,需要在D:\myjava中創(chuàng)建三個子文件夾,名字分別為management、student、teacher;其次,將Person_i.java拷入文件夾myjava中;然后再將Student_i.java中的三個類的源代碼分開寫成三個類文件,將Assistant_i.java拷入management文件夾中,將Student_i.java拷入student文件夾中,將Professor_i.java拷入teacher文件夾中,最后依次改寫這四個程序并編譯為字節(jié)碼文件。3.5.3自定義包(1)設(shè)置classpath3.5.3自定義包Person_i.java程序改為:packageschool;/**文件:Person_i.java說明:《Java實用教程》例3.13**/publicclassPerson_i{……//類體的代碼與例3.9中一樣}使用下面的編譯命令,可將Person_i.java編譯為Person_i.class文件。D:\myjava\school>javacPerson_i.java3.5.3自定義包Person_i.java程序改為:3.5.3自定義包Student_i.java程序改為:packageschool.student;//把Student_i類放入包school的子包student中/**文件:Student_i.java說明:《Java實用教程》例3.13**/importschool.Person_i;//由于Student_i類要繼承超類Person_i,所以需要先導(dǎo)入該類//子類Student_i,繼承超類Person_ipublicclassStudent_iextendsPerson_i{ protectedStringdept;//子類變量 staticprivateintcount=0;3.5.3自定義包Student_i.java程序改為:3.5.3自定義包 publicStudent_i(Stringn,inta,Stringd) { super(n,a); dept=d; setKind("Student");//調(diào)用從超類繼承的方法 count++; } publicstaticintgetCount() { returncount; } publicvoidwork() { System.out.println("Havingclasses"); } }3.5.3自定義包 publicStudent_i(S3.5.3自定義包使用下面的兩種編譯命令,都可將Student_i.java編譯為Student_i.class文件。D:\myjava\school\student>javacStudent_i.javaD:\>javacD:\myjava\school\student\Student_i.javaAssistant_i.java程序改為:packageschool.management;//把Assistant_i類放入包school的子包management中/**文件:Assistant_i.java說明:《Java實用教程》例3.13**/importschool.Person_i;//子類Assistant_i,繼承超類Person_i3.5.3自定義包使用下面的兩種編譯命令,都可將Stud3.5.3自定義包publicclassAssistant_iextendsPerson_i{ protectedStringdept; staticprivateintcount=0; publicAssistant_i(Stringn,inta,Stringd) { super(n,a); dept=d; setKind("Assistant"); count++; } publicstaticintgetCount() { returncount; }3.5.3自定義包publicclassAssist3.5.3自定義包publicvoidwork() { System.out.println("Talkingwithastudent"); } publicvoidsub_print() {super.work();System.out.println("子類對象的個數(shù):this.count="+this.getCount());System.out.println("超類對象的個數(shù):super.count="+super.getCount()); } }如上例所示,使用兩種方法,都可將Assistant_i.java編譯為Assistant_i.class文件。D:\>javacD:\myjava\school\management\Assistant_i.java3.5.3自定義包publicvoidwork()3.5.3自定義包Professor_i.java程序改為:packageschool.teacher;//把Professor_i類放入包school的子包teacher中/**文件:Professor_i.java說明:《Java實用教程》例3.13**/importschool.Person_i;//子類Professor_i,繼承超類Person_ipublicclassProfessor_iextendsPerson_i{ protectedStringdept; staticprivateintcount=0;
3.5.3自定義包Professor_i.java程序改3.5.3自定義包publicProfessor_i(Stringn,inta,Stringd) { super(n,a); dept=d; setKind("Professor"); count++; }publicstaticintgetCount() { returncount; } publicvoidwork() { System.out.println("Teaching"); } }3.5.3自定義包publicProfessor_i(3.5.3自定義包我們使用下面的語句將Professor_i.java編譯為Professor_i.class文件。D:\>javacD:\myjava\school\teacher\Professor_i.java(3)編寫信息系學(xué)生的新類Is程序代碼為:packageschool.student;//把Is類放入包school的子包student中/**文件:Is.java說明:《Java實用教程》例3.13**///由于本類中要調(diào)用Person_i等四個類,所以需要先導(dǎo)入importschool.Person_i;importschool.student.*;3.5.3自定義包我們使用下面的語句將Professor3.5.3自定義包importschool.teacher.*;importschool.management.*;//子類Is,繼承超類Student_ipublicclassIsextendsStudent_i{ staticprivateintcount=0; publicIs(Stringn,inta) { super(n,a,"信息系");//調(diào)用超類的構(gòu)造方法 setKind("StudentofInformationDepartment"); count++; } publicstaticintgetCount() { returncount; }3.5.3自定義包importschool.teach3.5.3自定義包publicvoidwork() { System.out.println("Programming..."); } publicstaticvoidmain(Stringargs[]){//創(chuàng)建school包和其各個子包中的每個類的實例對象Person_ip=newPerson_i("Jack",50);p.work();Student_is=newStudent_i("Peter",20,"投資系");s.work();Isi=newIs("Gates",18);
3.5.3自定義包publicvoidwork()3.5.3自定義包i.work();Assistant_ia=newAssistant_i("Steven",36,"會計系");a.work();Professor_ipr=newProfessor_i("Rose",48,"電子系");pr.work();System.out.println("count="+Person_i.getCount());} }將Is.java保存在D:\myjava\school\student中,經(jīng)過編譯生成字節(jié)碼文件Is.class,運行程序后,結(jié)果如圖3-3所示。3.5.3自定義包i.work();3.5.3自定義包圖3-3信息系學(xué)生類Is的編譯與運行3.5.3自定義包圖3-3信息系學(xué)生類Is的編譯與運3.5.3自定義包程序說明:信息系學(xué)生的類Is與其超類Student_i同時存放在D:\myjava\school\student目錄中,所以在兩個類聲明包的代碼是一樣的。由于要在Is中創(chuàng)建包中所有類的對象,所以在程序的第7行至第10行使用import語句先導(dǎo)入Person_i等類。因為各個類的move方法都是用public修飾的,所以都可以調(diào)用。Person_i.getCount()獲取的是Person_i類的對象的個數(shù)。在創(chuàng)建五個類的對象時,由于有繼承關(guān)系,所以最終都要調(diào)用Person_i類的構(gòu)造方法Person_i(Stringn,inta),使得count的值增1。要注意的是,Java編譯器使用文件分隔符和.java擴(kuò)展對文件操作,而Java解釋器則使用.分隔符裝載類,如圖3-3所示。3.5.3自定義包程序說明:3.5.3自定義包歸納注釋:從這個實例看,把類放入包中,可總結(jié)如下的操作步驟(以將公用類Student_i放在包school的子包student中為例):(1)創(chuàng)建與包結(jié)構(gòu)一致的文件夾D:\myjava\school\student。(2)為環(huán)境變量classpath添加值:setclasspath=.;D:\myjava(3)在源程序Student_i.java中,聲明Student_i類放在包student中:packageschool.student;importschool.Person_i;publicclassStudent_iextendsPerson_i聲明包的語句放在類的聲明前,如果聲明的類的超類不在同一包中,必須先使用import語句導(dǎo)入超類。3.5.3自定義包歸納注釋:3.5.3自定義包(4)編譯類將源程序Student_i.java編譯后生成的Student_i.class文件拷入D:\myjava\school\student文件夾中。(5)引用包中的類在其他類中可用import語句引用student包中聲明的類Student_i:importschool.student.*;publicclassIsextendsStudent_i引用包的語句放在類聲明之前。3.5.3自定義包(4)編譯類3.5.3自定義包思考:1.如果在類Is的main()方法體中添加語句System.out.println(p.kind);程序能否順利編譯?如果能,運行結(jié)果是什么?為什么?若在類Is的main()方法體中又添加語句System.out.println();程序能否順利編譯?為什么?2.若在類Is的main()方法體中添加語句p.eat();,程序編譯時會有什么錯誤?為什么?如何修改程序使eat()方法中的語句能夠輸出?3.設(shè)計一個的新類School_lx,把該類添加到school包中,并在School_lx中創(chuàng)建包中除本類外的所有類的實例對象,且所有對象都調(diào)用各自類的move方法。3.5.3自定義包思考:3.6接口和內(nèi)部類前面的內(nèi)容,我們已經(jīng)學(xué)習(xí)了Java面向?qū)ο缶幊痰乃谢竟ぞ摺T诒竟?jié),我們簡單介紹兩種高級技巧。第一項技術(shù)叫做接口(interface),用來描述類的功能,而不指明具體的實現(xiàn)方式。一個類可以實現(xiàn)一個或多個接口,只要類實現(xiàn)了接口,就可以在任何需要該接口的地方使用這個類的對象。第一項技術(shù)叫做內(nèi)部類,內(nèi)部類有些復(fù)雜——它們定義在其他類的內(nèi)部,其方法可以訪問外殼類的成員變量。內(nèi)部類主要用于設(shè)計相互協(xié)作的類的集合尤其在編寫那些除了圖形用戶界面事件的代碼時,使用內(nèi)部類可以使代碼更為簡潔和專業(yè)。3.6.1接口3.6.2內(nèi)部類3.6接口和內(nèi)部類前面的內(nèi)容,我們已經(jīng)學(xué)習(xí)了Java面向3.6.1接口Java不支持多重繼承,即一個類只能有一個超類。單繼承性使得Java簡單,易于管理程序。但在實際應(yīng)用中,經(jīng)常需要使用多重繼承功能,為了克服單繼承的缺點,Java使用了接口。1.接口聲明在Java中,接口只含有一些常量和抽象方法,它不是類,而是一組對類的要求,這些類要與接口一致。所以,接口就是一種標(biāo)準(zhǔn)、一些規(guī)范,只要大家都使用同一種接口寫程序,這些程序之間就很容易互相訪問。接口的聲明與類的聲明相似,格式為:[<修飾符>]interface<接口名>[extends<接口名>]{聲明常量1;聲明常量2;方法1;方法2;}3.6.1接口Java不支持多重繼承,即一個類只能有一3.6.1接口其中,修飾符只有兩種情況:public或省略修飾符。定義在接口中的常量全部隱含為final和static,所以不需要自己為常量加final和static修飾符,同時這意味著它們就是類常量,不會被實現(xiàn)接口方法的類改變,這些變量還必須設(shè)置初值。接口中的方法都是抽象方法,所以接口可以說是一個完全抽象的類。但一個類中所有的方法都是抽象的,它也不一定是一個接口,因為抽象類中除了抽象方法外,還可能有成員變量。如果接口聲明為public,則接口中的方法和變量全部為public。例3.14聲明接口。3.6.1接口其中,修飾符只有兩種情況:public或省3.6.1接口我們使用下面的語句將Player.java編譯為Player.class文件。D:\myjava>javacPlayer.java注意:接口中的方法都是抽象方法,而一個抽象方法不需要編寫方法的內(nèi)容,也就是說當(dāng)方法聲明完后,就直接以分號“;”來結(jié)束,不用加上左右大括號,就像程序中第8行到第10行那樣。這點要非常注意,因為如果加上了大括號,及時括號里沒有任何的程序代碼,它還是完成了方法的實現(xiàn)。3.6.1接口我們使用下面的語句將Player.java3.6.1接口2.實現(xiàn)接口接口的實現(xiàn)類似于繼承,只是不用extends,而是用關(guān)鍵字implements聲明一個類將實現(xiàn)一個或多個接口,其聲明格式如下:[<修飾符>]class<類名>[extends<超類名>][implements<接口名1>,<接口名2>,……]其中,〈修飾符〉可以是public,也可以省略。如果一個類實現(xiàn)一個接口,則必須實現(xiàn)接口中的所有方法,且方法必須聲明為public。如果一個類實現(xiàn)多個接口,則用逗號分隔接口列表。一個類實現(xiàn)一個接口,必須給出接口中所有方法的實現(xiàn)。如果不能實現(xiàn)某方法,也必須寫出一個空方法。Java允許多個類實現(xiàn)同一個接口,這些類之間可以是毫無聯(lián)系的,每個類各有自己實現(xiàn)方法的細(xì)節(jié)。同時,一個類也能實現(xiàn)多個接口,這就解決了多重繼承的問題,如圖3-4所示3.6.1接口2.實現(xiàn)接口3.6.1接口超類Super子類Sub1子類Sub2繼承繼承(a)單重繼承機(jī)制超類Super子類Sub接口1接口2實現(xiàn)繼承實現(xiàn)(b)多重繼承機(jī)制圖3-4繼承機(jī)制3.6.1接口超類子類子類繼承繼承(a)單重繼承機(jī)制超3.6.1接口接口的語法規(guī)則很容易記住,但真正理解接口更重要。那為什么要使用接口呢?例如,公共汽車、電影院、滑雪場、科技城、兒童樂園等場所都具有收費的功能,我們可以分別聲明相應(yīng)的類,如公共汽車類、電影院類等。過去的做法是為這些類聲明一個超類,在超類中定義收費方法,當(dāng)這些類繼承超類時,覆蓋收費方法。但是這些類之間幾乎沒有聯(lián)系,不能聲明某一個類作為它們的超類,所以舊辦法行不通。另外,即使能聲明超類,但是象公共汽車類還需要繼承客車類,而Java是不允許多重繼承的,那么此時,收費就可定義為一個接口,其中聲明收費的方法charge是空方法,由各個類實現(xiàn)收費接口時具體實現(xiàn)收費方法。例3.15一個類實現(xiàn)多個接口。3.6.1接口接口的語法規(guī)則很容易記住,但真正理解接口更3.6.2內(nèi)部類1.認(rèn)識內(nèi)部類內(nèi)部類(InnerClass)是在一個類的內(nèi)部嵌套定義的類,它可以是其它類的成員,也可以在一個語句塊的內(nèi)部定義,還可以在表達(dá)式內(nèi)部匿名定義,匿名類是一種特殊的內(nèi)部類,它是在一個表達(dá)式內(nèi)部包含一個完整的類定義。我們把包含內(nèi)部類的類稱為外部類。內(nèi)部類有如下特性:一般用在定義它的類或語句塊之內(nèi),在外部引用它時必須給出完整的名稱。名字不能與包含它的類名相同。可以使用包含它的類的靜態(tài)和實例成員變量,也可以使用它所在方法的局部變量??梢远x為abstract??梢月暶鳛閜rivate或protected。若被聲明為static,就變成了頂層類,不能再使用局部變量。若想在InnerClass中聲明任何static成員,則該InnerClass必須聲明為static。使用內(nèi)部類既有優(yōu)點又有缺點:優(yōu)點:節(jié)省編譯后產(chǎn)生的字節(jié)碼文件的大小缺點:使程序結(jié)構(gòu)不清楚例3.16使用內(nèi)部類體現(xiàn)封裝性3.6.2內(nèi)部類1.認(rèn)識內(nèi)部類3.6.2內(nèi)部類2.靜態(tài)內(nèi)部類和普通的類一樣,內(nèi)部類也可以有靜態(tài)的。不過和非靜態(tài)內(nèi)部類相比,區(qū)別就在于靜態(tài)內(nèi)部類沒有了指向外部的引用。這實際上和C++中的嵌套類很相像了,Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用這一點上,當(dāng)然從設(shè)計的角度以及以它一些細(xì)節(jié)來講還有區(qū)別。除此之外,在任何非靜態(tài)內(nèi)部類中,都不能有靜態(tài)數(shù)據(jù),靜態(tài)方法或者又一個靜態(tài)內(nèi)部類(內(nèi)部類的嵌套可以不止一層)。不過靜態(tài)內(nèi)部類中卻可以擁有這一切。這也算是兩者的第二個區(qū)別吧。3.6.2內(nèi)部類2.靜態(tài)內(nèi)部類3.6.2內(nèi)部類3.局部內(nèi)部類Java內(nèi)部類也可以是局部的,它可以定義在一個方法甚至一個代碼塊之內(nèi)。例3.17局部內(nèi)部類。3.6.2內(nèi)部類3.局部內(nèi)部類3.6.2內(nèi)部類4.匿名內(nèi)部類Java的匿名內(nèi)部類(AnonymousInnerClass)的語法規(guī)則看上去有些古怪,不過當(dāng)你只需要創(chuàng)建一個類的對象而且用不上它的名字時,使用內(nèi)部類可以使代碼看上去簡潔清楚。它的語法規(guī)則是這樣的:newinterfacename(){......};或者newsuperclassname(){......};例3.18使用匿名內(nèi)部類。3.6.2內(nèi)部類4.匿名內(nèi)部類習(xí)題
一、問答題1.什么是類?什么是對象?它們之間的關(guān)系是怎樣的?2.Java設(shè)置了幾種類成員的訪問權(quán)限?各表示什么含義?3.為什么要將類封裝起來?封裝的原則是什么?4.什么是繼承?什么是多態(tài)?方法的重載和覆蓋有何區(qū)別?5.談?wù)勀銓γ嫦驅(qū)ο蟪绦蛟O(shè)計的理解。6.為什么Java要采用單重繼承?Java怎樣實現(xiàn)多重繼承機(jī)制?7.定義內(nèi)部類有什么好處?8.Java的API采用什么組織方式?怎樣使用Java定義好的類?9.構(gòu)造方法是否可以被繼承?是否可以被重載?試舉例。10.什么是包?它的作用是什么?如何創(chuàng)建包并引用其中的類?習(xí)題
一、問答題習(xí)題
二、填空題1.Java語言中,調(diào)用方法時,參數(shù)傳遞是值調(diào)用,而不是()調(diào)用。2.接口是一種只含有抽象方法或()的一種特殊抽象類。3.Object類是Java所有類的()。4.new是()對象的操作符。5.在一個類的內(nèi)部嵌套定義的類稱為()。習(xí)題
二、填空題習(xí)題
三、選擇題1.下列說法中,哪個是正確的?A)類是變量和方法的集合體B)數(shù)組是無序數(shù)據(jù)的集合C)抽象類可以實例化D)類成員數(shù)據(jù)必須是公有的2.下面對形參的說法,哪個是正確的?A)必須有多個B)至少有一個C)可以沒有D)只能是簡單變量3.構(gòu)造方法何時被調(diào)用?A)類定義時B)創(chuàng)建對象時C)調(diào)用對象方法時D)使用對象的變量時4.下列對繼承的說法,哪個是正確的?A)子類能繼承父類的所有方法和狀態(tài)B)子類能繼承父類的非私有方法和狀態(tài)C)子類只能繼承父類public方法和狀態(tài)D)子類只能繼承父類的方法,而不能繼承狀態(tài)習(xí)題
三、選擇題習(xí)題
5.下面有關(guān)接口的說法,哪個是正確的?A)接口與抽象類是相同的概念B)實現(xiàn)一個接口必須實現(xiàn)接口的所有方法C)接口之間不能有繼承關(guān)系D)一個類可實現(xiàn)多個接口習(xí)題
5.下面有關(guān)接口的說法,哪個是正確的?習(xí)題
四、編程題1.設(shè)計銀行賬戶類及存取款操作方法。其中銀行賬戶類Account中包括:賬戶信息:賬號、姓名、開戶時間、身份證號碼等。存款方法:put()。取款方法:get()。查看賬戶現(xiàn)有金額方法:howmatch()。要求:銀行賬戶類聲明為public,其中的成員變量聲明為private,方法聲明為public。2.閱讀下面的程序,對程序運行結(jié)果進(jìn)行分析。下面的程序文件名為School.java,存放在目錄D:\myjava\school中,程序中把類School添加到相應(yīng)的包中,在編譯運行后分析運行結(jié)果。習(xí)題
四、編程題習(xí)題
packageschool;/** 文件:School.java**/importschool.Person_i;importschool.student.*;publicclassSchool{ publicstaticvoidmain(Stringargs[]){Islee=newIs("Philip",18);lee.work();((Student_i)lee).work();((Person_i)lee).work();} }/**習(xí)題
packageschool;習(xí)題
編譯:D:\>javacD:\myjava\school\School.java運行:D:\>javaschool.School分析為什么程序運行結(jié)果為:Programming...Programming...Programming...而不是:Programming...HavingclassesWorking...**/習(xí)題
編譯:習(xí)題
因為Islee=newIs("Philip",18)語句創(chuàng)建了信息系學(xué)生類Is的對象lee,類Is的work()方法中只有輸出字符串“Programming...”的功能,所以lee.work()語句輸出了該字符串;(Student_i)lee是將lee強(qiáng)制轉(zhuǎn)換類型為Student_i類型,但是無論類型轉(zhuǎn)換為何種類型,lee依然還是類Is的對象,所以仍舊執(zhí)行類Is的work()方法,故此仍然輸出字符串“Programming...”,而不是執(zhí)行Student_i類的work()方法(輸出字符串“Havingclasses”);同樣的道理,((Person_i)lee).work()仍然輸出字符串“Programming...”,而不是執(zhí)行Person_i類的work()方法(輸出字符串“Working...”)。習(xí)題
因為Islee=newIs("Philip",18習(xí)題
3.編寫一個接口定義,產(chǎn)生一年的12個月的一組常量為:1,2,3,4,5,6,7,8,9,10,11,12。//用接口實現(xiàn)常量組publicinterfaceMonths{intJANUARY=1,FEBRUARY=2,MARCH=3,APRIL=4;intMAY=5,JUNE=6,JULY=7,AUGEST=8;intSEPTEMBER=9,OCTOBER=10,NOVEMBER=11,DECEMBER=12;}習(xí)題
3.編寫一個接口定義,產(chǎn)生一年的12個月的一組常量為:習(xí)題
習(xí)題
習(xí)題
publicclassAccount{privateStringid,id_name,id_time,id_card;privateintvalue;Account(Stringa,Stringb,Stringc,Stringd,inte){id=a;id_name=b;id_time=c;id_card=d;value=e;}publicvoidget(intv){if(value>=v){value=value-v;System.out.println("已取出"+v+"元。");}習(xí)題
publicclassAccount習(xí)題
else{System.out.println("余額不足,已取出"+value+"元。");value=0;}}publicvoidput(intv){value=value+v;System.out.println("已存入"+v+"元。");}publicvoidhowmatch(){System.out.println("該帳戶余額為:"+value);}習(xí)題
else習(xí)題
publicstaticvoidmain(Stringargs[]){ Accounta1=newAccount("123","張平","2006-10-23","789654",500); a1.howmatch(); a1.put(600); a1.howmatch(); a1.get(1300); a1.howmatch();}}習(xí)題
publicstaticvoidmain(St第3章Java面向?qū)ο缶幊堂嫦驅(qū)ο蟮能浖_發(fā)和相應(yīng)的面向?qū)ο蟮某绦蛟O(shè)計方法是當(dāng)今計算機(jī)技術(shù)發(fā)展的重要成果和趨勢之一。Java是一種完全面向?qū)ο蟮某绦蛟O(shè)計語言,它的所有數(shù)據(jù)類型和函數(shù)都封裝在類中。Java所實現(xiàn)的封裝、繼承、多態(tài)性等面向?qū)ο蟮膶傩裕档土顺绦虻膹?fù)雜性,實現(xiàn)了代碼的可重用性,提高了運行效率,使Java不依賴于機(jī)器的結(jié)構(gòu),具有平臺無關(guān)性、分布式、可移植性、可重用性、健壯性、安全性等特點。3.1面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ)3.2類與對象3.3成員變量和成員方法的定義與實現(xiàn)3.4類的繼承與多態(tài)3.5包3.6接口和內(nèi)部類習(xí)題第3章Java面向?qū)ο缶幊堂嫦驅(qū)ο蟮能浖_發(fā)和相應(yīng)的面學(xué)習(xí)目標(biāo)
【學(xué)習(xí)目標(biāo)】了解面向?qū)ο缶幊痰幕纠碚摵突靖拍?,掌握面向?qū)ο缶幊痰幕痉椒ǎ瑢W(xué)習(xí)后能夠編寫體現(xiàn)OOP風(fēng)格的Java程序?!颈菊轮R點】類和對象的概念面向?qū)ο蟮奶匦灶愖兞亢皖惙椒ǖ氖褂梅庋b和修飾符的使用內(nèi)部類的使用接口的使用包層次的理解和使用學(xué)習(xí)目標(biāo)【學(xué)習(xí)目標(biāo)】3.1面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ)3.1.1面向?qū)ο蟾攀?.1.2面向?qū)ο笾械幕靖拍?.1.3面向?qū)ο蟪绦蛟O(shè)計方法的優(yōu)點3.1面向?qū)ο蟪绦蛟O(shè)計基礎(chǔ)3.1.1面向?qū)ο蟾攀?.1.1面向?qū)ο蟾攀鲈缙谟嬎銠C(jī)中運行的程序大都是為特定的硬件系統(tǒng)專門設(shè)計的,稱為面向機(jī)器的程序。這類程序的運行速度和效率都很高,但是可讀性和可移植性很差,隨著軟件開發(fā)規(guī)模的擴(kuò)大,這類面向機(jī)器的程序逐漸被以C為代表的面向過程的程序所取代。面向過程問題求解的核心組成是數(shù)據(jù)結(jié)構(gòu)和算法。其中數(shù)據(jù)結(jié)構(gòu)利用計算機(jī)的離散邏輯來量化表達(dá)需要解決的問題,而算法則研究如何快捷、高效地組織解決問題的具體過程。面向過程的程序設(shè)計是以具體的的解體過程為研究和實現(xiàn)的主體,可以精確、完備地描述具體的求解過程(這里的過程通常是指操作),但卻不足以把一個包含了多個相互關(guān)聯(lián)的過程的復(fù)雜系統(tǒng)表述清楚。面向?qū)ο蟮某绦蛟O(shè)計不僅關(guān)心孤立的單個過程,還關(guān)心包含這些過程的復(fù)雜系統(tǒng),它能夠使計算機(jī)邏輯來模擬描述系統(tǒng)本身,包括系統(tǒng)的組成、系統(tǒng)的各種可能狀態(tài),以及系統(tǒng)中可能產(chǎn)生的各種過程與過程引起的系統(tǒng)狀態(tài)切換。3.1.1面向?qū)ο蟾攀鲈缙谟嬎銠C(jī)中運行的程序大都是為特定3.1.2面向?qū)ο笾械幕靖拍?.類與對象對象的概念是面向?qū)ο蠹夹g(shù)的核心所在。實際生活中,我們每時每刻都與“對象”打交道,比如屋頂上的貓、學(xué)生用的課桌、老王的彩色電視機(jī)等,甚至我們自己本身也是一個對象。我們平時怎樣稱呼對象呢?我們會以這個對象分類的名稱來稱呼它,例如城市里有很多貓、大街上有很多車、我要去看電視等等,這里的貓、車、課桌、電視都只是對象的一種分類而已。在Java中,我們稱之為類。面向?qū)ο蠹夹g(shù)中另一個重要概念就是類,類是模板也是藍(lán)圖,從類中構(gòu)造一個對象,即創(chuàng)建了一個類的實例。類好比一個建材市場,其中有許多子類——各種各樣的裝飾材料,而我們裝修自己的房子就要選擇我們需要的材料(為了建
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 全縣輿情調(diào)研報告范文
- 清明實踐報告范文
- 2025年度木材代理進(jìn)口合同模板(含檢疫標(biāo)準(zhǔn))
- 2025年度足療養(yǎng)生館連鎖經(jīng)營權(quán)及商標(biāo)轉(zhuǎn)讓合同書
- 二零二五年度學(xué)生安全保障與家長責(zé)任書
- 2025年度電力安全監(jiān)督電力安裝工程勞務(wù)分包協(xié)議
- 二零二五年度智慧物流項目預(yù)算執(zhí)行書
- 二零二五年度手摩托線上線下銷售渠道合作合同
- 2025年度旅游咨詢兼職合同
- 檳榔品牌2025年度線上線下聯(lián)合代理協(xié)議
- 班主任能力大賽情景答辯環(huán)節(jié)真題及答案高中組
- 軸對稱圖形(課件)-2023-2024學(xué)年二年級下冊數(shù)學(xué)人教版-1
- 定制公司用工合同范本
- 2024年四川省成都市雙流區(qū)中考物理第二次適應(yīng)性考試試卷
- 2024年岳陽職業(yè)技術(shù)學(xué)院單招職業(yè)技能測試題庫附答案
- 2024年江西司法警官職業(yè)學(xué)院單招職業(yè)適應(yīng)性測試題庫含答案
- 精神科護(hù)士進(jìn)修
- 2024年洛陽市九年級語文中考第一次模擬考試卷附答案解析
- 脾淋巴瘤護(hù)理查房
- (幻燈片)湘教版七年級下冊地理復(fù)習(xí)課件
- 2024年江西電力職業(yè)技術(shù)學(xué)院單招職業(yè)技能測試題庫及答案解析
評論
0/150
提交評論