第3章面向?qū)ο骭第1頁
第3章面向?qū)ο骭第2頁
第3章面向?qū)ο骭第3頁
第3章面向?qū)ο骭第4頁
第3章面向?qū)ο骭第5頁
已閱讀5頁,還剩47頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Java語言09-10學年度第一學期08計算機王德力第3章面向?qū)ο竺嫦驅(qū)ο蟮娜齻€特征:封裝、繼承、多態(tài)3.1

類與對象

面向?qū)ο蟮木幊趟枷肓D使在計算機語言中對事物的描述與現(xiàn)實世界中該事物的本來面目盡可能地一致,類(class)和對象(object)就是面向?qū)ο蠓椒ǖ暮诵母拍?。類是對某一類事物的描述,是抽象的、概念上的定義;對象是實際存在的該類事物的個體,因而也稱實例。如:人(類),張三(對象),其中張三具有人的特性和行為。面向?qū)ο蟪绦蛟O(shè)計的重點是類的設(shè)計,而不是對象的設(shè)計。

3.1.1類的定義

類可以將數(shù)據(jù)和函數(shù)封裝在一起,其中數(shù)據(jù)表示類的屬性,函數(shù)表示類的行為。定義類就是要定義類的屬性與行為(方法)。如:

classPerson{

intage;voidshout(){

System.out.println(“myageis:”+age);}}

其中,定義了一個Person類,該類有一個屬性age,一個方法shout。類的屬性也叫類的成員變量,類的方法也叫類的成員函數(shù)。一個類中的方法可以直接訪問同類中的任何成員(包括成員變量和成員函數(shù))。3.1.2對象的產(chǎn)生與使用要想實現(xiàn)類的屬性與行為,必須創(chuàng)建具體的對象。要創(chuàng)建新的對象,需要使用new關(guān)鍵字和想要創(chuàng)建對象的類名,如:

Personp1=newPerson();

等號左邊以類名Person作為變量類型定義了一個變量p1,來指向等號右邊通過new關(guān)鍵字創(chuàng)建的一個Person類的對象實例對象,變量p1就是對象的引用句柄,對象的引用句柄是在棧中分配的一個變量,對象本身是在堆中分配的。當一個對象被創(chuàng)建時,會對其中各種類型的成員變量自動進行初始化賦值。比如數(shù)值為0,字符為空,布爾型為假。創(chuàng)建新的對象后,就可以用“對象名.對象成員”的格式,來訪問對象的成員(屬性和方法)。例:TestPerson.java

3.1.3對象的比較有兩種方式可用于對象間的比較,它們是“==”與equals()方法,“==”操作符用于比較兩個變量的值是否相等,equals()方法用于比較兩個對象的內(nèi)容是否一致。例:Compare.java3.1.4匿名對象創(chuàng)建完對象,在調(diào)用該對象的方法時,也可以不定義對象的句柄,而直接調(diào)用這個對象的方法。這樣的對象叫做匿名對象,如:newPerson().shout();

這句代碼沒有產(chǎn)生任何句柄,而是直接用new關(guān)鍵創(chuàng)建了Person類的對象并直接調(diào)用它的shout()方法。使用匿名對象的兩種情況:(1)如果一個對象只需要進行一次方法調(diào)用,那么就可以使用匿名對象。(2)將匿名對象作為實參傳遞一個函數(shù)調(diào)用,如:

getSomeOne(newPerson());3.1.5實現(xiàn)類的封裝性 在定義一個類的成員(包括變量和方法)時,使用private關(guān)鍵字說明這個成員的訪問權(quán)限,這個成員成了類的私有成員,只能被這個類的其它成員方法調(diào)用,而不能被其它的類訪問。例:TestPerson2.javapublic為公共的,可以在任意類中訪問這類成員。為了實現(xiàn)良好的封裝性,通常將類的成員變量聲明為private,再通過public的方法來對這個變量進行訪問。這種方式被稱為封裝,實現(xiàn)封裝可以達到以下目的:隱藏類的實現(xiàn)細節(jié);讓使用者只能通過事先定制好的方法來訪問數(shù)據(jù),可以方便地加入控制邏輯,限制對屬性的不合理操作;便于修改,增強代碼的可維護性;可進行數(shù)據(jù)檢查。3.2構(gòu)造函數(shù)3.2.1構(gòu)造函數(shù)的定義與作用構(gòu)造方法在程序設(shè)計中非常有用,它可以為類的成員變量進行初始化工作,當一個類的實例對象剛產(chǎn)生時,這個類的構(gòu)造方法就會自動調(diào)用,我們可以在這個方法中加入要完成初始化工作的代碼。構(gòu)造方法不同于一般方法:

它具有與類相同的名稱它不含返回值它不能在方法中用return語句返回一個值例:PersonConstru.java

3.2.2構(gòu)造方法的重載構(gòu)造方法也可以被重載。例:PersonConstru2.java

在Java的每個類里都至少有一個構(gòu)造方法,如果程序員沒有在一個類里定義構(gòu)造方法,系統(tǒng)會自動為這個類產(chǎn)生一個默認的構(gòu)造方法,這個默認構(gòu)造方法沒有參數(shù),在其方法體中也沒有任何代碼。由于系統(tǒng)提供的默認構(gòu)造方法往往不能滿足需求,我們可以自己定義類的構(gòu)造方法來滿足需要,一旦編程者為該類定義了構(gòu)造方法,系統(tǒng)就不再提供默認的構(gòu)造方法了。3.3this引用句柄例:TestThis.java問題:如何在func2中調(diào)用a1的func1?答:this.func1();this關(guān)鍵字在java程序里的作用和它的詞義很接近,它在函數(shù)內(nèi)部就是這個函數(shù)所屬的對象的引用變量。在成員方法中,對訪問的同類中成員前不加this引用,效果是一樣的,如上例:func1();每個成員方法內(nèi)部,都有一個this引用變量,指向調(diào)用這個方法的對象。有些情況下,必須用this關(guān)鍵字(1)想通過構(gòu)造方法將外部傳入的參數(shù)賦值給類成員變量,構(gòu)造方法的形式參數(shù)名稱與類的成員變量名相同。如:

classA{Stringname; publicA(Stringname) {=name;}}不能用name=name的形式,因為形式參數(shù)是方法內(nèi)部的一個局部變量,成員變量與方法中的局部變量同名時,在該方法中對同名變量的訪問是指那個局部變量。(2)假設(shè)有一個容器類和一個部件類,在容器類的某個方法中要創(chuàng)建部件類的實例對象,而部件類的構(gòu)造方法要接收一個代表其所在容器的參數(shù),程序代碼為:

classContainer{Componentcomp;publicvoidaddComponent(){comp=newComponent(this);}}classComponent{ContainermyContainer;publicComponent(Containerc){myContainer=c;}}

這就是通過this引用把當前的對象作為一個參數(shù)傳遞給其他的方法和構(gòu)造方法的應(yīng)用。(3)構(gòu)造方法是在產(chǎn)生對象是被java系統(tǒng)自動調(diào)用的,我們不能在程序中像調(diào)用其他方法一樣去調(diào)用構(gòu)造方法。但我們可以在一個構(gòu)造方法里調(diào)用其他重載的構(gòu)造方法,不是用構(gòu)造方法名,而是用this(參數(shù)表)的形式,根據(jù)其中的參數(shù)列表,選擇相應(yīng)的構(gòu)造方法。例:

publicclassPerson{Stringname;

intage;publicPerson(Stringname){=name;}publicPerson(String

name,intage){this(name);this.age=age;}}

在類Person的第二個構(gòu)造方法中,通過this(…)調(diào)用,執(zhí)行第一個構(gòu)造方法中的代碼。3.4函數(shù)的參數(shù)傳遞3.4.1基本數(shù)據(jù)類型的參數(shù)傳遞方法的參數(shù)傳遞過程中方法的形式參數(shù)相當于方法中定義的局部變量,方法調(diào)用結(jié)束時也就釋放了,不會影響到主程序中同名的局部變量.

例:PassValue.java3.4.2引用數(shù)據(jù)類型的參數(shù)傳遞例:PassRef.java對象的引用變量并不是對象本身,它們只是對象的句柄(名稱),就好象一個人可以有多個名稱一樣,一個對象可以有多個句柄。Java語言在給被調(diào)用方法的參數(shù)賦值時,只采用傳值的方式。所以,基本數(shù)據(jù)類型傳遞的是該數(shù)據(jù)的本身,引用數(shù)據(jù)類型傳遞的也是這個變量的值本身,即對象的引用(句柄),而非對象本身,通過方法調(diào)用,可以改變對象的內(nèi)容。3.5static關(guān)鍵字3.5.1靜態(tài)變量當我們編寫一個類時,其實就是在描述其對象的屬性和行為,而并沒有產(chǎn)生實質(zhì)上的對象,只有通過new關(guān)鍵字才會產(chǎn)生出對象,這時系統(tǒng)才會分配內(nèi)存空間給對象,其方法才可以供外部調(diào)用。有時候,我們希望無論是否產(chǎn)生了對象或無論產(chǎn)生了多少對象的情況下,某些特定的數(shù)據(jù)在內(nèi)存空間中只有一份,可以通過:類名.成員變量的形式訪問它,要實現(xiàn)這個效果,只需要在類中定義的變量前面加上static關(guān)鍵字即可,我們稱這種變量為靜態(tài)變量。靜態(tài)變量在某種程度上與其它語言的全局變量類似,如果不是私有的就可以在類的外部進行訪問,此時不需要產(chǎn)生類的實例對象,只需類名就可以引用。例:TestChinese.java用static標識符修飾的變量,它們在類被載入時創(chuàng)建,只要類存在,static變量就存在。由于靜態(tài)成員變量能被各實例對象所共享,我們可以用它來實現(xiàn)一些特殊效果,如統(tǒng)計產(chǎn)生對象數(shù):classA{privatestaticintcount=0;publicA(){count=count+1;}}3.5.2靜態(tài)方法我們有時也希望不必創(chuàng)建對象就可以調(diào)用某個方法,換句話說也就是使該方法不必和對象綁在一起。要實現(xiàn)這個效果,只需要在類中定義的方法前加上static關(guān)鍵字即可,我們稱這種方法為靜態(tài)成員方法。同靜態(tài)成員變量一樣,可以用類名直接訪問靜態(tài)成員方法,也可以用類的實例對象來訪問靜態(tài)成員方法,還可以在類的非靜態(tài)的成員方法中象訪問其它非靜態(tài)方法一樣去訪問這個靜態(tài)方法,如:

TestChinese2.java類的靜態(tài)成員經(jīng)常被稱為“類成員”,對于靜態(tài)成員變量,我們叫做類屬性,對于靜態(tài)成員方法,我們叫類方法。采用static關(guān)鍵字說明類的屬性和方法不屬于類的某個實例對象,在前面用到的System.out.println()語句,其中,System是一個類名,out是System類的一個靜態(tài)成員變量,println()方法則是out所引用的對象的方法。在使用類的靜態(tài)方法時,要注意以下幾點:(1)在靜態(tài)方法里只能直接調(diào)用同類中其它的靜態(tài)成員(包括變量和方法),而不能直接訪問類中的非靜態(tài)成員。因為對于非靜態(tài)的方法和變量,需要先創(chuàng)建類的實例對象后才可使用,而靜態(tài)方法在使用前不用創(chuàng)建任何對象。(2)靜態(tài)方法不能以任何方式引用this和super關(guān)鍵字。(3)main()方法是靜態(tài)的,因此JVM在執(zhí)行main方法時不創(chuàng)建main方法所在類的實例對象,因而在main()方法中,不能直接訪問該類中的非靜態(tài)成員,必須創(chuàng)建該類的一個實例對象后,才能通過這個對象去訪問類中的非靜態(tài)成員。3.5.3理解main方法的語法前面已經(jīng)知道,如果一個類要被Java解釋器直接裝載運行,這個類中必須有main()方法,現(xiàn)在可以理解main方法的定義了。由于Java虛擬機需要調(diào)用類的main()方法,所以該方法的訪問權(quán)限必須是public,又因為Java虛擬機在執(zhí)行main()方法時不必創(chuàng)建對象,所以該方法必須是static的,該方法接收一個String類型的數(shù)組,該數(shù)組中保存執(zhí)行Java命令時傳遞給所運行的類的參數(shù)。3.6內(nèi)部類在一個類的內(nèi)部定義類,這就是嵌套類,也叫內(nèi)部類、內(nèi)置類。嵌套類可以直接訪問嵌套它的類的成員,包括private成員,但是,嵌套類的成員卻不能被嵌套它的類直接訪問。3.6.1類中定義的內(nèi)部類在類中直接定義的嵌套類的使用范圍,僅限于這個類的內(nèi)部,也就是說,A類里定義了一個B類,那么B為A所知,卻不被A的外面所知。內(nèi)部類的定義和普通類的定義沒什么區(qū)別,它可以直接訪問和引用它的外部類的所有變量和方法。例:InnerClassDemo.java在上例程序中,內(nèi)部類Inner定義在Outer類的范圍之內(nèi),因此,在Inner類之內(nèi)的display()方法可以直接訪問Outer類的變量outer_i。其實,在內(nèi)部類對象保存了一個外部類對象的引用,當內(nèi)部類的成員方法中訪問某一變量時,如果在該方法和內(nèi)部類中都沒有定義過這個變量,調(diào)用就會被傳遞給內(nèi)部類中保存的那個外部類對象的引用,通過那個外部類對象的引用去調(diào)用這個變量,在內(nèi)部類中調(diào)用外部類的方法也是一樣的道理。一個內(nèi)部類可以訪問它的外部類的成員,但是反過來就不成立了。內(nèi)部類的成員只有在內(nèi)部類的范圍之內(nèi)是可知的,并不能被外部類使用。3.6.2內(nèi)部類如何被外部引用內(nèi)部類也可以通過創(chuàng)建對象從外部類之外被調(diào)用,只要將內(nèi)部類聲明為public即可,例:TestInner.java3.6.3方法中定義的內(nèi)部類嵌套類并非只能在類里定義,也可以在幾個程序塊的范圍之內(nèi)定義內(nèi)部類。例如,在方法中,或甚至在for循環(huán)內(nèi)部,都可以定義嵌套類。例:InnerClassDemo2.java3.7類的繼承面向?qū)ο蟮闹匾厣痪褪悄軌蚴褂靡郧敖ㄔ斓念惖姆椒ê蛯傩裕瑫?jié)省很多編程時間,而且更為重要的是,這樣可以減少代碼出錯的機會。這就是類的繼承。3.7.1繼承的特點例:Student.java程序中通過extends關(guān)鍵字來表明類Student具有類Person的所有屬性和方法。我們說Person類Student類的父類(也叫基類或超類),Student類是Person類的子類。在類的繼承中,有一些細節(jié)問題:(1)通過繼承可以簡化類的定義。(2)Java只支持單繼承,不允許多繼承。一個類只能有一個父類,不允許一個類直接繼承多個類,但一個類可以被多個類繼承。(3)可以有多層繼承,即一個類可以繼承某一個類的子類,如類B繼承了類A,類C又可以繼承類B,那么類C也間接繼承了類A。(4)子類繼承父類所有的成員變量和成員方法,但不繼承父類的構(gòu)造方法。

在子類的構(gòu)造方法中可以使用語句super(參數(shù)列表)調(diào)用父類的構(gòu)造方法。如:publicStudent(String

name,int

age,Stringschool){super(name,age);

this.school=school;}(5)如果子類的構(gòu)造方法中沒有顯示地調(diào)用父類構(gòu)造方法,也沒有使用this關(guān)鍵字調(diào)用重載的其它構(gòu)造方法,則在產(chǎn)生子類的實例對象時,系統(tǒng)默認調(diào)用父類無參數(shù)的構(gòu)造方法。但此時如果父類中沒有無參數(shù)的構(gòu)造方法,則編譯出錯。所以,在定義類時,只要定義了有參數(shù)的構(gòu)造方法,通常都還需要定義一個無參數(shù)的構(gòu)造方法。3.7.2子類對象的實例化過程如:Personp=newPerson(“zs”,19);(1)分配成員變量的存儲空間并進行默認的初始化。(2)綁定構(gòu)造方法參數(shù)。如將“zs”和19賦值給構(gòu)造方法中的形式參數(shù)變量。(3)如有this調(diào)用,則調(diào)用相應(yīng)的重載構(gòu)造方法。(4)顯式或隱式追溯調(diào)用父類的構(gòu)造方法。(5)進行實例變量的顯式初始化操作,也就是執(zhí)行在定義成員變量時就對其進行賦值的語句。(6)執(zhí)行當前構(gòu)造方法的方法體中和程序代碼。其中super(…)this(…)調(diào)用語句不能同時在一個構(gòu)造函數(shù)中出現(xiàn)。super(…)或this(…)調(diào)用語句只能作為構(gòu)造函數(shù)中的第一句出現(xiàn)。3.7.3覆蓋父類的方法在子類中可以根據(jù)需要對從父類中繼承來的方法進行改造:方法的覆蓋(也叫重寫)。覆蓋方法必須和被覆蓋方法具有相同的方法名稱、參數(shù)列表和返回值類型。例:Student1.java3.7.4final關(guān)鍵字1.在java中聲明類、屬性和方法時,可使用關(guān)鍵字final來修飾。2final標記的類不能被繼承。3final標記的方法不能被子類重寫。4final標記的變量即成為常量,只能賦值一次。final標記的變量必須在聲明的同時或在該類的構(gòu)造方法中顯式賦值。3.8抽象類與接口3.8.1抽象類Java中可以定義一些不含方法體的方法,它的方法體的實現(xiàn)交給該類的子類根據(jù)自己的情況去實現(xiàn),這樣的方法就是抽象方法,包含抽象方法的類就叫做抽象類。一個抽象類中可以有一個或多個抽象方法。抽象方法必須用abstract修飾符來定義,任何帶有抽象方法的類都必須聲明為抽象類。1、抽象類定義規(guī)則抽象類必須用abstract關(guān)鍵字來修飾,抽象方法也必須用abstract來修飾。抽象類不能被實例化,也就是不能用new關(guān)鍵字去產(chǎn)生對象。抽象方法只需聲明,而不需實現(xiàn)。含有抽象方法的類必須被聲明為抽象類,抽象類的子類必須覆蓋所有的抽象方法后才能被實例化,否則這個子類還是個抽象類。2、抽象方法的寫法

abstract返回值類型抽象方法(參數(shù)列表);3、抽象類和抽象方法的例子

abstractclassA{abstractint

aa(int

x,inty);}注意:含有抽象方法的類肯定是抽象類,抽象類中的某個方法不一定是抽象的。3.8.2接口(interface)如果一個抽象類中的所有方法都是抽象的,就可以將這個類用另外一種方式來定義,也就是接口定義。接口是抽象方法和常量值的定義和集合,從本質(zhì)上講,接口是一種特殊的抽象類,這種抽象類中只包含常量和方法的定義,而沒有變量和方法的實現(xiàn)。如:

publicinterfaceRunner{

intID=1;voidrun();}在接口Runner的定義中,即使沒有顯式地將其中的成員用public關(guān)鍵字標識,但這些成員都是public訪問類型的。接口里的變量默認是用publicstaticfinal標識的。所以,接口中定義的變量就是全局靜態(tài)變量。我們可以定義一個新的接口,用extends關(guān)鍵字去繼承一個已有的接口;也可以定義一個類,用implements關(guān)鍵字去實現(xiàn)一個接口中的所有方法;還可以定義一個抽象的類,用implements關(guān)鍵字去實現(xiàn)一個接口中定義的部分方法。interfaceCanFight{voidfight();}interfaceCanSwim

{voidswim();}interfaceCanFly

{voidfly();}classActionCharacter{publicvoidfight(){}}classHeroextendsActionCharacterimplementsCanFight,CanSwim,CanFly

{publicvoidswim(){}publicvoidfly(){}}在java中,設(shè)計接口的目的是為了讓類不必受限于單一繼承的關(guān)系,而可以靈活地同時繼承一些共有的特性,從而達到多重繼承的目的。一個類可以在繼承一個父類的同時,實現(xiàn)一個或多個接口,extends關(guān)鍵字必須位于implements關(guān)鍵字之前。實現(xiàn)一個接口就是要實現(xiàn)該接口的所有方法(抽象類除外)接口中的方法都是抽象的。多個無關(guān)的類可以實現(xiàn)同一個接口,一個類可以實現(xiàn)多個無關(guān)的接口。3.9對象的多態(tài)性3.9.1對象的類型轉(zhuǎn)換子類對象能夠自動轉(zhuǎn)換成父類的。但父類的對象不能自動轉(zhuǎn)換成子類的,如需要,必須進行強制類型轉(zhuǎn)換。比如“男人”和“人”的關(guān)系。3.9.2面向?qū)ο蟮亩鄳B(tài)性例:Cdt.java盡管在callA(Aa)方法定義中,從字面上看是通過父類的引用類型變量a去調(diào)用其中的func1(),但實際執(zhí)行的是子類中的func1()方法,這是因為實際傳遞進來的對象確實是子類的實例對象,所以程序調(diào)用的是子類中的func1()方法。同一段程序代碼,卻有兩種截然不同的結(jié)果,這就是面向?qū)ο蟮亩鄳B(tài)性。多態(tài)性有如下特點:應(yīng)用程序不必為每一個子類編寫功能調(diào)用,只需要對抽象基類進行處理即可。子類的功能可以被基類的方法或引用變量調(diào)用,這叫做向后兼容,可以提高程序的可擴充性和可維護性。3.9.3匿名內(nèi)部類例:AnInner.java此例中,類Inner僅使用了一次,對于此程序,可以簡寫,在調(diào)用callInner方法時,不用事先定義類Inner,可以在給callInner方法傳遞參數(shù)時,臨時創(chuàng)建一個類A的匿名子類的實例對象。例:AnInner2.java

3.10包為了對類進行分門別類的管理,Java通過引入包機制,來解決此問題。3.10.1package語句及應(yīng)用例:TestPackage.java程序中第一條語句,批示這個源文件中的所有類都位于包.cysz中,位于包中的每個類的完整名稱都應(yīng)該是包名與類名的組合,如類TestPackage的完整名稱是:.cysz.TestPackage

同一個包中的類相互訪問,不用指定包名,如果從外部訪問一個包中的類,必須用類的完整名稱。如果在命令行中啟動Java虛擬機,解釋運行TestPackage類,必須用:java.cysz.TestPackage位于包中的類,在文件系統(tǒng)中的存放位置,必須有與包名層次相對應(yīng)的目錄結(jié)構(gòu)。在package語句中,用(.)來指明包的層次。所以例中的生成的類要放于源文件所在目錄下的cn\com\cysz目錄下。

當虛擬機要裝載.cysz.TestPackage類時,會沿著classpath環(huán)境變量指定的路徑中去逐一查找,查找這些路徑下是否有cn子目錄,接著在此目錄下查找com子目錄,再在下面去查找cysz子目錄,最后在此查找TestPackage.class文件。也可在編譯時

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論