面向對象技術(Java)課件第4章 面向對象原理進階_第1頁
面向對象技術(Java)課件第4章 面向對象原理進階_第2頁
面向對象技術(Java)課件第4章 面向對象原理進階_第3頁
面向對象技術(Java)課件第4章 面向對象原理進階_第4頁
面向對象技術(Java)課件第4章 面向對象原理進階_第5頁
已閱讀5頁,還剩28頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1課堂目標掌握類的靜態(tài)成員掌握繼承的概念和用法掌握final關鍵字用法

掌握抽象類的定義和用法掌握接口的定義和用法掌握多態(tài)的使用掌握包的定義和用法static關鍵字static是靜態(tài)的意思。在Java語言中,static關鍵字用來修飾類層次的成員,是屬于所有對象共享的;在類裝入后,可通過類名直接訪問,不需要先創(chuàng)建對象才能使用,static常有三種用法,分別是:static修飾成員變量,為類成員變量。static修飾成員方法,為類成員方法。static代碼塊,用來初始化類成員變量,當虛擬機加載類時自動執(zhí)行此代碼塊。靜態(tài)變量即類變量不管創(chuàng)建了類的多少實例,整個類中靜態(tài)變量的副本只有一個。

引用靜態(tài)變量的方法:通過引用類的任一實例通過類的名稱(建議)classStaticDemo{staticintx=0;

StaticDemo(){x++;}}StaticDemod1=newStaticDemo();StaticDemod2=newStaticDemo();d1.x=100;d2.x=200;testVariable=d1.x;

通過類實例訪問不是一個好方法StaticDemod1=newStaticDemo();StaticDemod2=newStaticDemo();

StaticDemo.x=100;StaticDemo.x=200;testVariable=StaticDemo.x;

聲明為static的變量實質上就是全局變量通過類名訪問靜態(tài)方法即類方法與靜態(tài)方法相關的幾個要點:類的靜態(tài)方法只能訪問其他的靜態(tài)成員靜態(tài)方法沒有this靜態(tài)方法不能被覆蓋為非靜態(tài)方法classStaticFun{staticinti=10;intj;

staticvoidsetValue(intx){

j=x;//出錯

System.out.println(""+i);}}不能訪問非靜態(tài)變量j,可以訪問靜態(tài)變量iclassStaticTest{staticvoidtest(){}}classStaticexextendsStaticTest{

voidtest(){}//出錯}

靜態(tài)塊如果需要通過計算來初始化靜態(tài)變量,可以聲明一個靜態(tài)塊。靜態(tài)塊僅在該類被加載時執(zhí)行一次。只能初始化類的靜態(tài)數據成員。

classTryInitialization{

staticint[]values=newint[10];//靜態(tài)數組成員

static{for(inti=0;i<values.length;i++)values[i]=(int)(100.0*Math.random());}}

static總結一般地,我們將沒有static修飾符修飾的變量稱為實例變量或對象層次的變量,它們和類變量的區(qū)別在于:l對于類變量(類層次),內存中只有一份,可通過類名或對象引用來訪問。l對于實例變量(對象層次),每創(chuàng)建一個對象,就會分配一次內存,即每個對象有一份內存。l類變量主要用來在各個對象之間共享數據或傳遞信號,實例變量主要描述的是對象特有的屬性或數據。在靜態(tài)方法中不能使用this關鍵字,也不能直接訪問所屬類的實例變量和實例方法。靜態(tài)代碼塊,它不屬于任何方法。JVM加載類時會自動執(zhí)行這些靜態(tài)代碼塊。如果類中包含多個靜態(tài)代碼塊,那么Java虛擬機將按照它們在類中出現的順序依次執(zhí)行,靜態(tài)代碼塊只執(zhí)行一次。靜態(tài)代碼塊也沒有this指針,也不能直接訪問對象層次的變量和方法,靜態(tài)代碼塊的作用主要是初始化復雜的類變量或其他加載類需要執(zhí)行的動作。封裝進階和單態(tài)設計模式結合私有構造方法和static關鍵字有一個經典的應用,那就是單態(tài)設計模式。什么是單態(tài)設計呢?單態(tài)設計模式就是指我們設計的類不能隨意的通過new來創(chuàng)建對象,在程序運行期間,只存在一個對象,該對象可完成所有的相關邏輯操作,不需要另外的對象。單態(tài)模式(也叫單例模式)的設計技巧如下:l將構造方法私有化,這樣外部就無法訪問構造方法,也就無法創(chuàng)建對象l定義一個該類的靜態(tài)類成員引用變量,在類加載時自動調用構造方法創(chuàng)建一個對象,有時需要使用靜態(tài)代碼塊完成復雜的構造過程。l再定義一個靜態(tài)成員方法,例如上例中的getInstance(),用來在需要時返回已經創(chuàng)建好的實例引用。通過多種設計模式的靈活運用可提高對象的封裝性,并提升類的可維護性和可擴展性,有興趣的同學可以參考設計模式相關的參考資料。繼承進階和super關鍵字Java語言不支持多重繼承,只支持單一繼承,即一個類只能有一個直接父類。例如以下代碼會導致編譯錯誤。classSubextendsBase1,Base2,Base3{…}//編譯錯誤Java的繼承和我們生物的繼承一樣,也是通過繼承形成類的層次模型,如圖4-1所示:Animal是Dog,Cat,Tiger的父類,Creature是Animal和Vegetation的父類,而Creature的父類是Object。所有的Java類都直接或間接地繼承了java.lang.Object類。繼承進階和super關鍵字this關鍵字代表對象本身;而在類的繼承關系中,我們用super關鍵字代表父類對象,通過super可以訪問被子類對象覆蓋了的方法或隱藏了的屬性。在程序中,在以下情況下一般會使用super關鍵字:l在類的構造方法中,通過super語句調用這個類的父類的構造方法。l在子類中訪問父類的被覆蓋的方法和被隱藏的屬性。注意:如果在子類的構造方法中通過super()調用父類的構造方法,則此調用必須出現在子類構造方法的可執(zhí)行語句的第一句。并且如果程序員沒有明確地調用父類的構造方法,編譯器會自動加一條調用父類的默認構造方法,所以除特殊情況外,我們一般建議應該對每一個類都給一個默認的構造方法。10方法覆蓋(override)方法覆蓋是Java實現多態(tài)性機制的另一種方式。在類層次結構中,如果子類中的一個方法與父類中的方法有相同的方法名并具有相同數量和類型的參數列表,這種情況稱為方法覆蓋。當一個覆蓋方法通過父類引用被調用,Java根據當前被引用對象的類型來決定執(zhí)行哪個版本的方法??梢酝ㄟ^super關鍵字調用直屬父類中被覆蓋的方法版本。11屬性隱藏和方法覆蓋示例classSuperClass{inta;SuperClass(){a=10;}

publicvoidprintA(){System.out.println("父類中a="+a);}}classSubClassextendsSuperClass{inta;SubClass(inta){this.a=a;}

publicvoidprintA(){System.out.println("子類中a="+a);}}

publicclassOverrideDemo{publicstaticvoidmain(Stringargs[]){SuperClasss1=newSubClass(20);

s1.printA();}}將調用子類的printA方法方法覆蓋與方法重載的異同方法覆蓋指的是在繼承關系中,子孫類對父類中繼承下來的方法進行了重寫,是在不同的類中;而方法重載指的是在同一個類中,有多個同名的方法,但方法的實現代碼各不相同。方法覆蓋要求子孫類中的方法聲明和父類中的方法聲明完全一樣,而方法重載則要求這些重載的方法它們的參數列表不一樣。被覆蓋的方法在程序運行時才能決定調用哪一個方法,即動態(tài)綁定。而重載的方法是在編譯時決定執(zhí)行哪一個方法的代碼,即編譯時采用靜態(tài)綁定。參考示例程序【例4-9】方法重寫和方法重載綜合演示繼承小結方法覆蓋是指在子類中對父類中繼承下來的方法給出一套新的實現代碼,并要求子類中的方法和父類中的方法的方法名、返回類型、參數個數和類型相同,否則就退變成了方法重載。屬性隱藏是指在子類中重新定義了父類中的成員變量,在子類對象中看不到父類中的成員變量。子類通過方法覆蓋和成員變量隱藏以及增加新的方法和屬性完成類的進化和完善,尤其對父類中比較抽象行為給出更具體的、符合自身的行為規(guī)范。參考程序【例4-8】。在Java繼承機制中要注意以下幾點:l構造方法不能被繼承。lprivate類型的成員變量和成員方法,不能被繼承。l覆蓋方法中不能縮小父類方法的訪問權限,但可擴大。l覆蓋方法中不能拋出比父類方法更多的異常。(異常參看第五章)l不能將靜態(tài)方法覆蓋為非靜態(tài)方法,也不能將非靜態(tài)方法覆蓋為靜態(tài)方法。l由于私有方法不能繼承,所以不存在覆蓋的問題。protected修飾的成員對其它包的子類是公開訪問權限的,非子類不可訪問。抽象進階和abstract關鍵字在面向對象方法中,抽象類主要用來進行類型隱藏。構造出一個具有相同行為模式的抽象描述,但是這些行為卻能夠有任意個可能的具體實現方式。這種抽象描述就形成了抽象類,而對這些行為的某種具體實現則表現為一個派生類。為了能夠實現面向對象設計的一個最核心的原則OCP(Open-ClosedPrinciple),抽象類是其中的關鍵所在。Java語言中,抽象用abstract關鍵字來說明,可以修飾類和方法,分別稱為抽象類和抽象方法。抽象類雖不能實例化,不能生成抽象類的對象,但能定義一個引用,引用可以指向具體子類的對象。抽象方法代表了某種接口標準,在子類中去具體實現功能。在設計中,如果父類方法中的某段代碼不確定,我們可以留給子類實現,就采用抽象方法的設計。參考示例程序【例4-10】抽象類和抽象方法測試使用abstract修飾符需要注意的規(guī)則:1.抽象類中可以沒有抽象方法,即定義類時,有abstract修飾符。但不管有沒有abstract修飾符,只要一個類包含了抽象方法,則此類自動變成抽象類。類中的抽象方法有三種方式獲得:l自己定義,即有abstract修飾符,沒有實現代碼。l從父類繼承而來。l從接口繼承而來。2.沒有抽象的構造方法,也沒有抽象的靜態(tài)方法。3.抽象類可以有構造方法,在子類調用構造方法時會級聯調用到。3.抽象類及抽象方法不能被final修飾,但抽象類可包含final方法。4.abstract和private、final、static連用是無意義的,會導致編譯錯誤。抽象進階和abstract關鍵字16instanceof關鍵字

classStudent{}classGraduateextendsStudent{}classUndergraduateStudentextendsStudent{}publicclassst{publicstaticvoidmain(String[]args){UndergraduateStudents1=newUndergraduateStudent();Graduates2=newGraduate();Studentx;

x=s1;if(xinstanceofUndergraduateStudent)System.out.println(“x是UndergraduateStudent類的實例?!?;elseSystem.out.println(“x是Graduate類的實例?!?;}}instanceof測試第一個參數的運行時類型是否為與第二個參數兼容的賦值。x在運行時指向s1,所以if語句條件返回truefinal關鍵字/final類final修飾符可應用于類、方法和變量。final在應用于類、方法和變量時意義是不同的,但本質是一樣的:final表示不可改變。

聲明為final的類不能被繼承。final類示例:

java.lang.String;java.lang.Math等

finalclassTestFinal{inti=7;intj=1;voidf(){}}classFurtherextendsTestFinal{}final類不能被繼承有繼承就有進化!而final關鍵字代表進化終止!final方法在方法聲明中使用final關鍵字向編譯器表明子類不能覆蓋此方法。在聲明類中,一個final方法只被實現一次。如果一個類為

final類,那么它的所有方法都為隱式的

final方法。classTestFinal{finalvoidf(){}}classFurtherextendsTestFinal{finalvoidf(){}}final方法不能被覆蓋final方法代表該行為的進化終止!final變量一個變量可以聲明為final,這樣做的目的是阻止它的內容被修改。聲明final變量后,只能被初始化一次,然后就不能對其值進行修改。一個final變量實質上是一個常量。

classFinalDemo{ publicstaticvoidmain(Stringargs[]){finalintnoChange=20;

noChange=30;

}}

final變量不能被修改interface關鍵字和接口Java語言中interface關鍵字用來定義接口或界面,此接口實際上是一種規(guī)范或標準。換句話說,接口就是法規(guī)、標準、規(guī)范、資格等等。例如要當律師,就要拿到律師資格證,要當會計師,就要考取注冊會計師,要當教師,就要取得教師資格證等等;換到設備制造領域也是如此,你要生產電視,就要參考相應的行業(yè)標準,要生產電腦主板,就要留有合適的插口等。在Java中也是如此,interface是我們設計或制定接口規(guī)范,不關心細節(jié),只關心功能和相應的數據指標要求,所以在Java的interface接口中只存在兩類東西,公有抽象的方法和公有靜態(tài)的常量。換句話說,不管程序員是否明確給出相應的修飾符,Java編譯器都會自動添加這些修飾符。Java接口的定義和使用接口的定義和類的定義很相似,語法如下:interface接口名[extends父接口列表]{//接口體,只包含公有抽象方法和常量}publicinterfacemyinterface{ publicabstractvoidadd(intx,inty); publicabstractvoidvolume(intx,inty,intz); publicstaticfinaldoubleprice=1450.00;publicstaticfinalintcounter=5;}注意:Java中接口之間是可以繼承的,并且可以是多繼承。如下所示:interfacesuperinterface1{}interfacesuperinterface2{}interfaceinterface_multi_fatherextendssuperinterface1,superinterface2{}接口的編譯同類是一樣的,使用javac進行編譯。接口編譯完后生成的還是字節(jié)碼文件,所以在Java中自定義的類型可以分為兩種,一種是類類型,一種是接口類型。Java接口的定義和使用一個類通過使用關鍵字implements聲明自己實現了一個或多個接口。如果實現多個接口,用逗號隔開,也就是說,雖然java類的繼承是單一的,但可以實現多個接口。如:classdemoimplementsmyinterfaceclassdemoimplementsMycalc,Mycount如果一個類實現了某個接口,跟類繼承機制一樣,此類自動會擁有接口中定義的常量和抽象方法。常量可以直接使用,但方法是抽象的,必須在類中提供具體的方法體,類才可以使用,否則,類就變成了抽象類,不能創(chuàng)建對象。一個Java源程序文件就是由類或接口組成的。前面已說過,接口也是類型,所以可以定義引用,但不能創(chuàng)建對象,那么接口定義的引用要指向什么對象呢?跟繼承機制中的父類引用指向子類對象一樣,接口定義的引用可指向實現了此接口的類創(chuàng)建的對象,并通過此引用可調用接口中定義的方法。參考示例程序【例4-12】【例4-13】多態(tài)進階在Java語言中如何體現多態(tài)呢?一般認為有兩種方式,一種是通過方法重載,靜態(tài)聯編的方式實現;一種是通過方法覆蓋(或方法重寫),動態(tài)聯編的方式實現?,F在我們說多態(tài)更多的是指動態(tài)的方式,即在運行時決定使用哪一段執(zhí)行代碼。在Java語言中,主要是通過父類引用或接口引用去調用子類對象的各種方法來實現多態(tài),參考示例程序【例4-14】【例4-17】【例4-18】,后面兩個示例要用到小應用程序的知識,需要用appletviewer程序查看執(zhí)行結果,請同學自己百度學習,程序執(zhí)行結果如下圖。枚舉、自動裝箱和拆箱JDK1.5以后Java語言引入了枚舉和自動裝箱機制??梢岳妹杜e給一個變量或者方法創(chuàng)建一系列的有效值,使用enum時,可以很容易地限制程序只能采用其中的某一個有效值。而自動裝箱和拆箱機制大大簡化了程序編程中重復的類型轉換工作。與其他語言中的枚舉類型相比,Java中的enum類型更加強大,其提供的enum是完整的類,所以提供了類可以得到的所有好處,允許添加任意的方法和字段,以及實現任意的接口等。enum類型的對象可以彼此比較,也可以被序列化。例如要創(chuàng)建一周中各天的列表,用枚舉聲明如下:enumWeekDays{MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;}這個聲明把整數序數賦給各個常量,即MONDAY=0,TUESDAY=1,以此類推。并可以添加toString方法或其他需要的方法。當定義一個枚舉類時,編譯器就會創(chuàng)建一個擴展java.lang.Enum類的類定義。這個類是java.lang.Object的一個直接后代。但與普通類不同的是,枚舉類具有以下屬性:l沒有公開的構造器,因此不可能把它實例化。l隱式為staticl每個枚舉常量其實只是一個實例對象,加載類時自動創(chuàng)建的。l可以調用枚舉類中的方法【例4-19】演示枚舉枚舉類枚舉、自動裝箱和拆箱自動裝箱(autoboxing)和拆箱(unboxing)用于自動地在基本數據類型及其封裝類對象之間進行轉換。在編程過程中,對于簡單的任務,使用基本類型很方便,因為可以對它們應用許多運算符而不必調用方法。但在有些場合,基本類型無法直接使用,只能使用封裝對象,例如在數據集合中,就只能使用對象,這時基本數據要做裝箱后才能使用,如以下代碼:

Integera=newInteger(100);//裝箱intb=2*Value();//拆箱從JDK1.5開始,不再需要這種顯式的裝箱和拆箱操作了,現在裝箱和拆箱是隱式自動地進行,由編譯器幫助我們完成,如【例4-20】演示。內部類和匿名類內部類是指在一個外部類的內部再定義一個類。內部類作為外部類的一個成員,是依附于外部類而存在的。內部類可以為靜態(tài),可用protected和private修飾(而外部類只能使用public和缺省的包訪問權限)。內部類主要有以下幾類:成員內部類、局部內部類、靜態(tài)內部類、匿名內部類。內部類允許把一些邏輯相關的類組織在一起,并且能控制內部類代碼的可視性。將包含此內部類的類稱為外部類或頂層類。參考示例程序【例4-21】和【例4-22】注意,如果一個內部類有static修飾,則此類自動變成和頂層類同級。即不能再直接訪問外部類非靜態(tài)成員變量。內部類要訪問的局部變量,局部變量必須定義成final類型。匿名內部類(簡稱匿名類)就是沒有名字的內部類。匿名類是一種特殊的內部類,這種類沒有名字,通過new關鍵字直接創(chuàng)建某一個類的匿名子類的對象來使用。什么情況下需要使用匿名內部類?如果滿足下面的一些條件,使用匿名內部類是比較合適的,示例【例4-23】:1、只用到類的一個實例。2、類在定義后馬上用到。3、類非常?。⊿UN推薦是在4行代碼以下)。4、給類命名并不會導致你的代碼更容易被理解。內部類和匿名類在使用匿名內部類時,要記住以下幾個原則:1、匿名內部類不能有構造方法。2、匿名內部類不能定義任何靜態(tài)成員、方法和類。3、匿名內部類不能是public,protected,private,static。4、只能創(chuàng)建匿名內部類的一個實例。5、一個匿名內部類一定是在new的后面,用其隱含實現一個接口或實現一個類。6、因匿名內部類為局部內部類,所以局部內部類的所有限制都對其生效。package關鍵字和包Java語言中提供了管理類和其他資源的包關鍵字package。包主要有三個作用:l包允許將類組合成較大的管理單元。l有助于避免命名沖突。l包允許在更廣的范圍內保護類、數據和方法。

包可以是類、接口和子包的集合。包的定義方式如下:packagemypackage;//mypackage是包名如果源程序中定義了包,則此package語句必須出現在Java源程序的第一句(指有效語句)。在Java語言中,包還可以包含子包,子包用“.”分開,如。Java語言中包的層次嚴格對應于操作系統(tǒng)的目錄結構,換句話說,Java編譯器和虛擬機要找到某一個包中的類,首先要找到相應的目錄,在目錄中去找類和裝入字節(jié)碼。package關鍵字和包包的使用分兩種方式:l包名.類名例mypackage.

溫馨提示

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

最新文檔

評論

0/150

提交評論