項目7 類與對象_第1頁
項目7 類與對象_第2頁
項目7 類與對象_第3頁
項目7 類與對象_第4頁
項目7 類與對象_第5頁
已閱讀5頁,還剩31頁未讀 繼續(xù)免費閱讀

付費下載

下載本文檔

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

文檔簡介

Java程序設計專業(yè)核心課程

精品課程1教學計劃ORJECT了解面向對象的編程思想。掌握如何定義類。掌握類的成員變量、成員方法。掌握權限修飾符。掌握如何創(chuàng)建對象。掌握對象的創(chuàng)建、比較和銷毀。1精品課程27.1面向對象概述在程序開發(fā)初期,人們使用結構化開發(fā)語言,但是隨著時間的流逝,軟件的規(guī)模越來越龐大,結構化語言的弊端也逐漸暴露出來,如開發(fā)周期被無休止地拖延,產(chǎn)品的質量也不盡如人意,人們終于發(fā)現(xiàn)結構化語言已經(jīng)不再適合當前的軟件開發(fā)。這時人們開始將另一種開發(fā)思想引入到程序中,即面向對象的開發(fā)思想。面向對象思想是人類最自然的一種、思考方式,它將所有預處理的問題抽象為對象,并了解這些對象具有哪些相應的屬性,以及展示這些對象的行為,以解決這些對象面臨的一些實際問題,面向對象設計實質上就是對現(xiàn)實世界的對象進行建模操作。7.1.1?對象現(xiàn)實世界中,隨處可見的事物就是對象,對象是事物存在的實體,如人類、書桌、計算機、高樓大廈等。人類解決問題的方式總是將復雜的事物簡單化,于是就會思考這些對象都是由哪些部分組成的。通常都會將對象劃分為兩部分:動態(tài)部分與靜態(tài)部分。3精品課程靜態(tài)部分,顧名思義,就是不能動的部分,這部分被稱為“屬性”,任何對象都會具備其自身屬性,例如,一個人,具有高矮、胖瘦、性別、年齡等屬性,然而具有這些屬性的人會執(zhí)行哪些動作也是一個值得探討的部分,這個人可以哭泣、微笑、說話、行走等,這些是這個人具備的行為(動態(tài)部分),人類通過探討對象的屬性和觀察對象的行為來了解對象。面向對象程序設計的思想,首先要將現(xiàn)實世界的實體抽象為對象,然后考慮這個對象具備的屬性和行為。例如,現(xiàn)在面臨一只大雁要從北方飛往南方這樣一個實際問題,試著以面向對象的思想來解決這一實際問題,參考步驟如下。(1)首先從這一問題中抽象出對象,這里抽象出的對象為大雁。(2)識別這個對象的屬性。對象具備的屬性都是靜態(tài)屬性,例如,大雁有一對翅膀、黑色的羽毛等。(3)識別這個對象的動態(tài)行為,即這只大雁可以進行的動作,如飛行、覓食等,這些行為都是因為這個對象基于其屬性而具有的動作。(4)識別出這些對象的屬性和行為后,這個對象就被定義完成了,然后可以根據(jù)這只大雁具有的特性來制訂這只大雁要從北方飛向南方的具體方案。實際上,大部分的鳥類都具有以上的屬性和行為,可以將這些屬性和行為封裝起來以描述鳥類。由此可見,類實質上就是封裝對象屬性和行為的載體,而對象則是類抽象出來的一個實例。7.1.2?類不能將所謂的一個事物描述成一類事物,如不能將一只鳥稱為鳥類,如果需要對同一類事物進行描述,需要使用類這個概念。類就是同一類事物的統(tǒng)稱,如果將現(xiàn)實世界中的一個事物抽象成對象,類就是這類對象的統(tǒng)稱,如鳥類、家禽類、人類等。類是構造對象時所依賴的規(guī)范,如一只鳥具有一對翅膀,而它可以通過這對翅膀飛行。而基本上所有的鳥都具有翅膀這個特性和飛行的技能,這樣具有相同特性和行為的一類事物就稱為類,類的思想就是這樣產(chǎn)生的。即對象就是符合某個類定義所生成的實例。更為恰當?shù)拿枋鍪?,類是世間事物的抽象稱呼,而對象則是這個事物相對應的實體。如果面臨實際問題,通常需要將類實例化為對象來解決。例如,解決大雁南飛的問題,這里只能拿這只大雁來處理這個問題,不能拿大雁類或鳥類來解決。類是封裝對象的屬性和行為的載體,反過來說,具有相同屬性和行為的一類實體被稱為類。例如,一個鳥類,鳥類封裝了所有鳥的共同屬性和應具有的行為。定義完鳥類之后,可以根據(jù)這個類抽象出一個實體對象,最后通過實體對象來解決相關的一些實際問題。在Java語言中,對象的行為是以方法的形式定義的,對象的屬性是以成員變量的形式定義的,而類包括對象的屬性方法,有關鳥類結構類的具體實現(xiàn)會在后續(xù)章節(jié)中進行介紹。7.1.3?面向對象的特點1.封裝4精品課程5精品課程封裝是面向對象編程的核心思想,而將對象的屬性和行為封裝起來的載體就是類,類通常對客戶隱藏其實現(xiàn)細節(jié)。例如,用戶使用計算機,只需要使用手指敲擊鍵盤就可以實現(xiàn)一些功能,用戶無須知道計算機內(nèi)部是如何工作的,即使用戶可能碰巧知道計算機的工作原理,但在使用計算機時并不完全依賴于計算機的工作原理等這些細節(jié)。采用封裝的思想保證了類內(nèi)部數(shù)據(jù)結構的完整性,應用該類的用戶不能輕易直接操縱此數(shù)據(jù)結構,而只能執(zhí)行類允許公開的數(shù)據(jù)。這樣避免了外部對內(nèi)部數(shù)據(jù)的影響,進而提高程序的可維護性。使用類實現(xiàn)封裝的特性如圖7-5所示。

圖7-5封裝特性示意圖2.繼承類與類之間同樣具有關系,如一個百貨公司類與銷售員類相聯(lián)系,這種關系被稱為關聯(lián),一般為二次元關系,再如學生類與教師類也是一個關聯(lián)。兩個類之間的關聯(lián)還有很多種,而繼承是關聯(lián)中的一種。當處理一個問題時,可以將一些有用的類保留下來,以便當遇到同樣問題時拿來復用。如需要解決信鴿送信的問題。由于鴿子也屬于鳥類,具有鳥類相同的屬性和行為,人們便可以在創(chuàng)建信鴿類時將鳥類拿來復用,并且保留鳥類具有的屬性和行為。由于鴿子也屬于鳥類,具有鳥類相同的屬性和行為,人們便可以在創(chuàng)建信鴿類時將鳥類拿來復用,并且保留鳥類具有的屬性和行為。6精品課程不過,并不是所有的鳥類都送信,因此還需要再添加一些信鴿所具有的屬性及行為。即鴿子類保留了鳥類的屬性和行為,這樣就節(jié)省了定義鳥和鴿子共同具有的屬性和行為的時間,這就是繼承的基本思想。而使用繼承思想也可以縮短軟件開發(fā)的時間,還可以提高系統(tǒng)性能,減少系統(tǒng)在使用過程中出現(xiàn)錯誤的概率。繼承性主要利用特定對象之間的共有屬性。例如,平行四邊形是四邊形(正方形、矩形也都是四邊形),平行四邊形與四邊形具有共同特性,就是擁有4個邊,那么可以將平行四邊形類看作是四邊形的延伸。平行四邊形復用了四邊形的屬性和行為,同時添加了平行四邊形獨有的屬性和行為(如平行四邊形的對邊平行且相等),這里可以將平行四邊形類看作是從四邊形類中繼承而來的。在Java語言中,將類似于平行四邊形的類稱為子類,將類似于四邊形的類稱為父類或超類。值得注意的是,可以說平行四邊形是特殊的四邊形,但不能說四邊形是平行四邊形,也就是說,子類的實例都是父類的實例,但不能說父類的實例是子類的實例。圖形類之間的繼承關系如圖7-6所示。圖7-6圖形類層次結構示意圖從圖7-6中可以看出,繼承關系可以使用樹形關系來表示,父類與子類存在一種層次關系。一個類處于繼承體系中,它既可以是其他類的父類,為其他類提供屬性和行為,也可以是其他類的子類,繼承父類的屬性和方法,如三角形既是圖形類的子類,同時也是等邊三角形的父類。3.多態(tài)將父類對象應用于子類的特征就是多態(tài)。依然以圖形類來說明多態(tài),如果將子類的對象統(tǒng)一看作超類的實例對象,這樣當繪制任何圖形時,可以簡單地調用父類即可,也就是以繪制圖形類的方法即可繪制任何圖形,這就是多態(tài)最基本的思想。多態(tài)允許以統(tǒng)一的風格編寫程序,以處理種類繁多的已存在的類及相關類。該統(tǒng)一風格可以由父類來實現(xiàn),就可以實例化子類的對象。由于整個事件的處理都只依賴于父類的方法,所以以后只要維護和調整父類的方法即可,這樣既降低了維護的難度,又節(jié)省了時間。在提到多態(tài)的同時,又不得不再次提到抽象類和接口,因為多態(tài)的實現(xiàn)并不依賴于具體類,而是依賴于抽象類和接口。再回到繪制圖形的實例上來,作為所有圖形的父類圖形類,其具有繪制圖形的方法,這個方法可以稱為“繪制圖形”,但如果要執(zhí)行這個“繪制圖形”命令,沒人知道應該畫什么樣的圖形,并且如果要在圖形類中抽象出一個圖形對象,沒有人能說清這個圖形究竟是什么樣,所以使用“抽象”這個詞匯來描述圖形類比較恰當。在Java語言中,這樣的類稱為抽象類,抽象類不能實例化對象。在多態(tài)的機制中,父類通常會被定義為抽象類,在抽象類中給出一個方法的標準,而不給出實現(xiàn)的具體流程。實際上這個方法也是抽象的,例如,圖形類中的“繪制圖形”方法只提供一個可以繪制圖形的標準,并沒有提供具體繪制圖形的流程,因為沒有人知道究竟需要繪制什么形狀的圖形。在多態(tài)機制中,比抽象類更為方便的方式是將抽象類定義為接口,即由抽象方法組成的集合就是接口。7精品課程接口的概念在現(xiàn)實中也極為常見,如從不同的五金商店買來的螺絲和螺絲釘,螺絲很輕松地就可以擰在螺絲釘上,雖然螺絲和螺絲釘?shù)膹S家可能不同,但這兩個物品可以很輕易地組合在一起,這是因為生產(chǎn)螺絲和螺絲釘?shù)膹S家都遵循著一個標準,這個標準在Java語言中就是接口。依然拿“繪制圖形”為例,可以將“繪制圖形”作為一個接口的抽象方法,然后使圖形類實現(xiàn)這個接口,同時實現(xiàn)“繪制圖形”這個抽象方法。而當需要繪制三角形類時,就可以繼承圖形類,重寫其中“繪制圖形”方法,改寫這個方法為“繪制三角形”,這樣就可以通過這個標準繪制不同的圖形。7.2類在7.1.2小節(jié)中已經(jīng)講解過類是封裝對象的屬性和行為的載體,而在Java語言中,對象的屬性以成員變量的形式存在,對象的方法以成員方法的形式存在。本節(jié)將介紹在Java語言中類是如何定義的。7.2.1?類的創(chuàng)建方法在類中除了成員方法之外,還存在一種特殊類型的方法,那就是構造方法。構造方法是一個與類同名的方法,對象的創(chuàng)建就是通過構造方法來完成的,每當實例化一個對象時,類都會自動調用構造方法,構造方法具有以下兩個特點。(1)構造方法沒有返回值。(2)構造方法的名稱要與本類的名稱相同。構造方法的定義語法格式如下:publicbook(){//…構造方法體}8精品課程其中,public為構造方法修飾符,book為構造方法的名稱。在構造方法中可以為成員變量賦值,這樣當實例化一個本類的對象時,相應的成員變量也將被初始化。在上文中介紹過this關鍵字,this關鍵字可以調用類的成員變量和成員方法,事實上,this還可以調用類中的構造方法?!纠?.1】在項目中創(chuàng)建AnyThting類,該類中使用this關鍵字調用構造方法。publicclassAnyThting{publicAnyThting(){//定義無參構造方法this("this調用有參構造方法");//使用this關鍵字調用有參構造方法System.out.println("無參構造方法");}publicAnyThting(Stringname){//定義有參構造方法System.out.println("有參構造方法");}}在例7.1中,可以看到定義了兩個構造方法,在無參構造方法中可以使用this關鍵字調用有參的構造方法,但使用這種方式需要注意,只可以在無參構造方法中的第一句使用this關鍵字調用有參構造方法。7.2.2?類的方法主方法是類的入口點,它定義了程序從何處開始;主方法提供對程序流向的控制,Java編譯器通過主方法來執(zhí)行程序。主方法的語法格式如下:publicstaticvoidmain(String[]args){//方法體}9精品課程10精品課程從主方法的定義中可以看到,主方法具有以下特性:(1)主方法是靜態(tài)的,若要直接在主方法中調用其他方法,則該方法必須也是靜態(tài)的。(2)主方法沒有返回值。(3)主方法的形參為數(shù)組。用args[0]~args[n]分別代表程序的第1~n個參數(shù),可以使用args.length獲取參數(shù)的個數(shù)。【例7.2】在項目中創(chuàng)建TestMain類,在主方法中編寫如下代碼,并在Eclipse中設置程序參數(shù)。publicclassTestMain{publicstaticvoidmain(String[]args){//定義主方法for(inti=0;i<args.length;i++){//根據(jù)參數(shù)個數(shù)做循環(huán)操作System.out.println(args[i]);//循環(huán)打印參數(shù)內(nèi)容}}}其運行結果如下:參數(shù)1參數(shù)2參數(shù)311精品課程在Eclipse中設置程序參數(shù)的步驟如下:(1)在Eclipse中選擇菜單欄中的“運行”→“運行”選項,彈出“運行”對話框。(2)選擇“自變量”選項卡,在“程序自變量”文本框中輸入相應的參數(shù),每個參數(shù)間按“Enter”鍵隔開。7.2.3?成員變量在Java語言中,對象的屬性稱為成員變量,又稱為屬性。為了使讀者更好地了解成員變量,首先定義一個圖書類Book,并在Book類中設置id、name和category這3個成員變量,分別對應于圖書編號、圖書名稱和圖書類別圖書屬性?!纠?.3】在項目中創(chuàng)建Book類,并在該類中定義與使用成員變量。publicclassBook{privateintid;//定義一個int型的成員變量privateStringname;//定義一個String型的成員變量privateStringcategory;//定義一個String型的成員變量publicStringgetName(){//定義一個getName()方法intid=0;//局部變量setName("Java");//調用類中其他方法returnid+;//設置方法返回值}privatevoidsetName(Stringname);//定義一個setName()方法=name;//將參數(shù)值賦予類中的成員變量}publicBookgetBook(){returnthis;//返回Book類引用}}從以上代碼中,可以看到在Java語言中使用class關鍵字來定義類,Book是類的名稱。同時在Book類中定義了3個成員變量,成員變量的類型可以設置為Java語言中合法的數(shù)據(jù)類型,其實成員變量就是普通的變量,可以為它設置初始值,也可以不為其設置初始置,如果不設置,則會有默認值。在3個成員變量前面有private關鍵字,表示用來定義一個私有成員(關于權限修飾符的說明將會在7.2.8小節(jié)中進行介紹)。7.2.4?成員方法在Java語言中,成員方法對應于類對象的行為。以Book類為例,它包含getName()和setName()兩個方法,分別為獲取圖書名稱和設置圖書名稱的方法。定義成員方法的語法格式如下:權限修飾符返回值類型方法名(參數(shù)類型參數(shù)名){//方法體return返回值;}一個成員方法可以有參數(shù),這個參數(shù)可以是對象也可以是基本數(shù)據(jù)類型的變量。同時,成員方法可以返回值和不返回任何值,如果需要返回值可以在方法體中使用return關鍵字,而使用這個關鍵字后,方法的執(zhí)行將被終止。成員方法的返回值可以是計算結果也可以是其他數(shù)值、對象,返回值類型要與方法返回值類型一致。在成員方法中可以調用其他成員方法和類成員變量,例如,在getName()方法中就調用了setName()方法,即將圖書名稱賦予一個值。同時在成員方法中可以定義一個變量,這個變量稱為局部變量(局部變量的內(nèi)容會在7.2.5小節(jié)中進行介紹)。12精品課程命令說明快捷鍵重命名重命名所選擇的

Java

元素Alt+Shift+R移動移動所選擇的

Java

元素Alt+Shift+V抽取方法創(chuàng)建一個包含當前所選語句或表達式的新方法,并相關的引用Alt+Shift+M抽取局部變量創(chuàng)建為當前所選表達式指定的新變量,并將選擇替換為對新變量的引用Alt+Shift+L命令說明快捷鍵重命名重命名所選擇的

Java

元素Alt+Shift+R移動移動所選擇的

Java

元素Alt+Shift+V抽取方法創(chuàng)建一個包含當前所選語句或表達式的新方法,并相關的引用Alt+Shift+M抽取局部變量創(chuàng)建為當前所選表達式指定的新變量,并將選擇替換為對新變量的引用Alt+Shift+L命令說明快捷鍵重命名重命名所選擇的

Java

元素Alt+Shift+R移動移動所選擇的

Java

元素Alt+Shift+V抽取方法創(chuàng)建一個包含當前所選語句或表達式的新方法,并相關的引用Alt+Shift+M抽取局部變量創(chuàng)建為當前所選表達式指定的新變量,并將選擇替換為對新變量的引用Alt+Shift+L命令說明快捷鍵重命名重命名所選擇的

Java

元素Alt+Shift+R移動移動所選擇的

Java

元素Alt+Shift+V抽取方法創(chuàng)建一個包含當前所選語句或表達式的新方法,并相關的引用Alt+Shift+M抽取局部變量創(chuàng)建為當前所選表達式指定的新變量,并將選擇替換為對新變量的引用Alt+Shift+L7.2.5?局部變量在上一小節(jié)中已經(jīng)介紹過成員方法,如果在成員方法內(nèi)定義一個變量,那么這個變量被稱為局部變量。例如,在例7.3定義的Book類中,getName()方法的id變量即為局部變量,實際上方法中的形參也可作為一個局部變量。例如,在定義setName(Stringname)方法時,Stringname這個形參就被看作局部變量。局部變量是在方法被執(zhí)行時創(chuàng)建,在方法執(zhí)行結束時被銷毀。局部變量在使用時必須進行賦值操作或被初始化,否則會出現(xiàn)編譯錯誤?!纠?.4】在項目中創(chuàng)建一個類文件,在該類中定義getName()方法并進行調用。publicStringgetName(){//定義一個getName()方法intid=0;//局部變量setName("Java");//調用類中其他方法returnid+;//設置方法返回值}如果將id這個局部變量的初始值去掉,編譯器將會出現(xiàn)編譯錯誤。7.2.6?局部變量的有效范圍可以將局部變量的有效范圍稱為變量的作用域,局部變量的作用域從該變量聲明的開始到該變量的結束為止。局部變量的作用域如圖7-7所示。圖7-7局部變量的作用域14精品課程在相互不嵌套的作用域中可以同時聲明兩個名稱、類型都相同的局部變量,如圖7-8所示。但是在相互嵌套的區(qū)域中不可以這樣聲明,如果將局部變量id值在方法體的for循環(huán)中再次定義,編譯器將會報錯,如圖7-9所示。圖7-8在不同嵌套區(qū)域中可以定義相同名稱與相同類型的局部變量圖7-9在方法體的嵌套區(qū)域中不可以定義相同名稱與相同類型的局部變量7.2.7?靜態(tài)變量、常量和方法在介紹靜態(tài)變量、常量和方法之前首先需要介紹static關鍵字,由static修飾的變量、常量和方法分別被稱作靜態(tài)變量、靜態(tài)常量和靜態(tài)方法。在處理問題時,會需要兩個類在同一個內(nèi)存區(qū)域中共享一個數(shù)據(jù)。例如,在球類中使用PI這個常量,可能除了本類需要這個常量之外,在另一個圓類中也需要使用這個常量。這時沒有必要在兩個類中同時創(chuàng)建PI這個常量,因為這樣系統(tǒng)會將這兩個不在同一個類中定義的常量分配到不同的內(nèi)存空間中,可以將這個常量設置為靜態(tài)的,PI常量在內(nèi)存中被共享的布局如圖7-10所示。圖7-10PI常量在內(nèi)存中被共享的布局被static修飾的變量、常量和方法被稱為靜態(tài)成員,靜態(tài)成員是屬于類所有的,區(qū)別于個別對象,可以在本類或其他類中使用類名和“.”運算符調用靜態(tài)成員。其語法格式如下:類名.靜態(tài)類成員【例7.5】在項目中創(chuàng)建StaticTest類,該類中的主方法調用靜態(tài)成員并在控制臺中輸出。publicclassStaticTest{staticdoublePI=3.1415;//在類中定義靜態(tài)常量staticintid;//在類中定義靜態(tài)變量publicstaticvoidmethod1(){//在類中定義靜態(tài)方法//方法體}publicvoidmethod2(){System.out.println(StaticTest.PI);//調用靜態(tài)常量System.out.println(StaticTest.id);//調用靜態(tài)變量StaticTest.method1();//調用靜態(tài)方法}}在例7.5中設置了3個靜態(tài)成員,分別為靜態(tài)常量、靜態(tài)變量和靜態(tài)方法,然后在method2()方法中分別調用這3個靜態(tài)成員,直接使用“類名.靜態(tài)成員”的形式進行調用即可。靜態(tài)成員與靜態(tài)方法的作用通常是為了提供共享數(shù)據(jù)或方法,如數(shù)據(jù)計算公式等,用static關鍵字聲明并實現(xiàn),當需要使用時,直接使用類名調用這些靜態(tài)成員即可。盡管使用這種方式調用靜態(tài)成員比較方便,但靜態(tài)成員同樣受public、private、protected修飾符的約束?!纠?.6】在項目中創(chuàng)建StaticTest類,該類中的主方法調用靜態(tài)成員并在控制臺中輸出。publicclassStaticTest{staticdoublePI=3.1415;//在類中定義靜態(tài)常量staticintid;//在類中定義靜態(tài)變量publicstaticvoidmethod1(){//在類中定義靜態(tài)方法//方法體}publicvoidmethod2(){System.out.println(StaticTest.PI);//調用靜態(tài)常量System.out.println(StaticTest.id);//調用靜態(tài)變量StaticTest.method1();//調用靜態(tài)方法}publicstaticStaticTestmethod3(){//在類中定義一個靜態(tài)方法method2();//調用非靜態(tài)方法returnthis;//在return語句中使用this關鍵字}}讀者也許會發(fā)現(xiàn),在Eclipse中輸入上述代碼后,編譯器會發(fā)生錯誤,這是因為method3()方法為一個靜態(tài)方法,而在其方法體中調用了非靜態(tài)方法和使用this關鍵字。在Java語言中對靜態(tài)方法有以下兩點規(guī)定。(1)在靜態(tài)方法中不可以使用this關鍵字。(2)在靜態(tài)方法中不可以直接調用非靜態(tài)方法。需要注意的是,在Java語言中規(guī)定不能將方法體內(nèi)的局部變量聲明為static。以下代碼就是錯誤的。publicclassexample{publicvoidmethod(){staticinti=0;}}在執(zhí)行類時,如果希望進行初始化,可以使用static定義一個靜態(tài)區(qū)域,例如:publicclassexample{static{//some}}當這段代碼被執(zhí)行時,首先執(zhí)行static塊中的程序,并且只會執(zhí)行一次。7.2.8?權限修飾符Java語言中的權限修飾符主要包括private、public和protected,這些修飾符控制著對類和類的成員本量,以及成員方法的訪問。如果一個類的成員變量或成員方法被private修飾,則該成員變量只能在本類中被使用,而在子類中是不可見的,并且對其他包的類也是不可見的。如果將類的成員變量和成員方法的訪問權限設置為public的,則除了可以在本類使用這些數(shù)據(jù)之外,還可以在子類和其他包中的類中使用。如果一個類的訪問權限被設置為private的,這個類將隱藏其內(nèi)的所有數(shù)據(jù),以免用戶直接訪問它。如果需要使類中的數(shù)據(jù)被子類或其他包中的類使用,可以將這個類設置為public訪問權限。如果一個類使用protected修飾符修飾,那么只有本包內(nèi),該類的子類或其他類可以訪問此類中的成員變量和成員方法?;诖?,public和protected修飾的類可以由子類訪問,如果子類和父類不在同一個包中,那么只有修飾符為public的類可以被子類訪問。如果父類不允許通過繼承產(chǎn)生的子類訪問它的成員變量,那么必須使用private修飾符聲明父類的這個成員變量。表7-1中描述了private、protected、public修飾符的修飾權限。表7-1Java語言中的修飾符的修飾權限訪問包位置privateprotectedpublic本類可見可見可見同包其他類或子類不可見可見可見其他包的類或子類不可見不可見可見【例7.7】在項目中的com.wsy包下創(chuàng)建AnyClass類,該類使用默認的訪問權限。packagecom.wsy;classAnyClass{publicvoiddoString(){//…方法體}}在上述代碼中,由于類的修飾符為默認修飾符,即只有一個包內(nèi)的其他類和子類可以對該類進行訪問,而AnyClass類中的doString()方法卻又被設置為public訪問權限,即使這樣,doString()方法的訪問權限依然與AnyClass類的訪問權限相同,因為Java語言規(guī)定,類的權限設定會約束類成員上的權限設定,所以上述代碼等同于例7.8中的代碼。【例7.8】示例代碼。packagecom.wsy;classAnyClass{voiddoString(){//…方法體}}7.2.9?this關鍵字【例7.9】在項目中創(chuàng)建一個類文件,該類中定義了setName()方法,并將方法的參數(shù)值賦予類中的成員變量。privatevoidsetName(Stringname){//定義一個setName()方法=name;//將參數(shù)值賦予類中的成員變量}從上述代碼中可以看到,成員變量與在setName()方法中的形式參數(shù)的名稱相同,都為name,那么如何在類中區(qū)分使用的是哪一個變量呢?Java語言規(guī)定使用this關鍵字來指定,this關鍵字被隱式地用于引用對象的成員變量和方法,如在上述代碼中,指定的就是Book類中的name成員變量,而=name語句中的第二個name則指定的是形參name。實質上setName()方法實現(xiàn)的功能就是將形參name的值賦予成員變量name。可以看到,this可以調用成員變量和成員方法,但這并不是Java語言中的最常規(guī)調用方式——使用“對象.成員變量”或“對象.成員方法”進行調用。既然this關鍵字可以調用成員變量和成員方法,那么究竟this關鍵字與對象之間具有怎樣的關系呢?事實上this引用就是對一個對象的引用。在setName()方法體中也可以使用name=name這種形式,可以在引用成員變量時省略this關鍵字,其結果與使用this關鍵字是一致的。既然使用this與沒有使用this的效果相同,那么為什么還要使用this關鍵字呢?其實this除了可以調用成員變量或成員方法之外,還可以作為方法的返回值?!纠?.10】在項目中創(chuàng)建一個類文件,該類中定義Book類型的方法,并通過this關鍵字進行返回。publicBookgetBook(){returnthis;//返回Book類引用}在getBook()方法中,方法的返回值為Book類,所以方法體中使用returnthis這種形式將Book類的對象進行返回。7.2.10?范例1:自定義圖書類在使用Java語言進行開發(fā)時,時刻要以面向對象的思想考慮問題。面向對象的基礎就是類,本范例將演示如何自定義類,它用于表示圖書。示例運行結果如下:書名:《數(shù)據(jù)安全與災備管理》作者:賈如春價格:49.00元(1)在項目中創(chuàng)建Book類,在類中定義3個成員變量,分別表示書名、作者和價格,同時提供構造方法和成員方法來修改成員變量。示例代碼如下:publicclassBook{privateStringtitle;//定義書名privateStringauthor;//定義作者privatedoubleprice;//定義價格publicBook(Stringtitle,Stringauthor,doubleprice){//利用構造方法初始化域this.title=title;this.author=author;this.price=price;}publicStringgetTitle(){//獲得書名returntitle;}publicStringgetAuthor(){//獲得作者returnauthor;}publicdoublegetPrice(){//獲得價格returnprice;}}(2)在com.mingrisoft包中創(chuàng)建類文件,名稱為Test。在該類的main()方法中,創(chuàng)建一個Book對象并輸出其屬性。示例代碼如下:publicclassTest{publicstaticvoidmain(Sting[]args){Bookbook=newBook("《java基礎》","李明","59.8");//創(chuàng)建對象System.out.println("書名:"+book.getTitle());//輸出書名System.out.println("作者:"+book.getAuthor());//輸出作者System.out.println("價格:"+book.getPrice()+"元");//輸出價格}}7.2.11?范例2:溫度單位轉換工具目前有兩種廣泛使用的溫度單位,分別為攝氏度和華氏度。在標準大氣壓下,沸騰的水可以表示成100攝氏度和212華氏度。本范例將編寫一個簡單的溫度單位轉換工具,可以將用戶輸入的攝氏度轉換成華氏度。示例運行結果如下:請輸入要轉換的溫度(單位:攝氏度)12轉換完成的溫度(單位:華氏度):53.6在項目中創(chuàng)建CelsiusConverter類,在類中定義了兩個方法,getFahrenheit()方法用于將攝氏溫度轉換成華氏溫度,main()方法用于測試。示例代碼如下:publicclassCelsiusConverter{publicdoublegetFahrenheit(doublecelsius){doublefahrenheit=1.8*celsius+32;//計算華氏溫度returnfahrenheit;//返回華氏溫度}publicstaticvoidmain(String[]args){System.out.println("請輸入要轉換的溫度(單位:攝氏度)");Scannerin=newScanner(System.in);//獲得控制臺輸入doublecelsius=in.nextDouble();//獲得用戶輸入的攝氏溫度CelsiusConverterconverter=newCelsiusConverter();//創(chuàng)建類的對象doublefahrenheit=converter.getFahrenheit(celsius);//轉換溫度為華氏度System.outprintln("轉換完成的溫度(單位:華氏度):"+Fahrenheit);}}7.3對象的應用Java是一門面向對象的程序設計語言,對象是由類抽象出來的,所有的問題都是通過對象來處理。對象可以操作類的屬性和方法解決相應的問題,所以了解對象的產(chǎn)生、操作和消亡對學習Java語言是十分必要的。本節(jié)將講解對象在Java語言中的應用。7.3.1?對象的創(chuàng)建在7.1節(jié)中已經(jīng)介紹過了對象,對象可以被認為是在一類事物中抽象出某一個特例,通過這個特例來處理這類事物出現(xiàn)的問題,在Java語言中可以通過new操作符來創(chuàng)建對象。在講解構造方法中介紹過每實例化一個對象就會自動調用一次構造方法,實質上這個過程就是創(chuàng)建對象的過程。準確地說,可以在Java語言中使用new操作符調用構造方法創(chuàng)建對象。其語法格式如下:Testtest=newTset();Testtest=newTest("a");參數(shù)說明如表7-2所示。表7-2創(chuàng)建對象語法中的參數(shù)說明設置值描述Test類名test創(chuàng)建Test類對象"a"構造方法的參數(shù)test對象被創(chuàng)建出來時,test對象就是一個對象的引用,這個引用在內(nèi)存中為對象分配了存儲空間可以在構造方法中初始化成員變量。當創(chuàng)建對象時,自動調用構造方法,也就是說,在Java語言中初始化與創(chuàng)建是被捆綁在一起的。每個對象都是相互獨立的,在內(nèi)存中占據(jù)獨立的內(nèi)存空間,并且每個對象都具有自己的生命周期,當一個對象的生命周期結束時,對象變成了垃圾,由Java虛擬機自帶的垃圾回收機制處理,不能再被使用(垃圾回收機制的內(nèi)容將會在7.3.5小節(jié)中進行介紹)。下面來看一個創(chuàng)建對象的實例?!纠?.11】在項目中創(chuàng)建CreateObject類,在類中創(chuàng)建對象并在主方法中創(chuàng)建對象。publicclassCreateObject{publicCreateObject(){//構造方法System.out.println("創(chuàng)建對象");}publicstaticvoidmain(Stringargs[]){//主方法newCreateObject();//創(chuàng)建對象}}運行結果如下:創(chuàng)建對象在上述實例的主方法中使用new操作符創(chuàng)建對象,在創(chuàng)建對象的同時,自動調用構造方法中的代碼。7.3.2?訪問對象的屬性和行為當用戶使用new操作符創(chuàng)建一個對象后,可以使用“對象.類成員”來獲取對象的屬性和行為。前文已經(jīng)提到過,對象的屬性和行為在類中是通過類成員變量和成員方法的形式來表示的,所以當對象獲取類成員,也就相應地獲取了對象的屬性和行為。【例7.12】在項目中創(chuàng)建TransferProperty類,該類中說明對象是如何調用類成員的。publicclassTransferProperty{inti=47;//定義成員變量publicvoidcall(){//定義成員方法System.out.println("調用call()方法");for(i=0;i<3;i++){System.out.println(i+"");if(i==2){System.out.println("\n");}}}publicTransferProperty(){//定義構造方法}publicstaticvoidmain(String[]args){TransferPropertyt1=newTransferProperty();//創(chuàng)建一個對象TransferPropertyt2=newTransferProperty();//創(chuàng)建另一個對象t2.i=60;//將類成員變量賦值為60//使用第一個對象調用類成員變量System.out.println("第一個實例對象調用變量i的結果:"+t1.i++);t1.call();//使用第一個對象調用類成員方法//使用第二個對象調用類成員變量System.out.println("第二個實例對象調用變量i的結果:"+t2.i++);t2.call();//使用第二個對象調用類成員方法}}其運行結果如下:第一個實例對象調用變量i的結果:47調用call()方法012第二個實例對象調用變量i的結果:60調用call()方法012在上述代碼的主方法中首先實例化一個對象,然后使用“.”操作符調用類的成員變量和成員方法。但是從運行結果可以看到,雖然使用兩個對象調用同一個成員變量,結果卻不相同,因為在打印這個成員變量的值之前將該值重新賦值為60,但在賦值時使用的是第二個對象t2調用成員變量,所以在第一個對象t1調用成員變量打印該值時仍然是該成員變量的初始值。由此可見,兩個對象的產(chǎn)生是相互獨立的,改變了t2的i值,不會影響到t1的i值。在內(nèi)存中這兩個對象的布局如圖7-11所示。圖7-11內(nèi)存中t1、t2兩個對象的布局如果希望成員變量不被其中任何一個對象改變,可以使用static關鍵字(前文曾經(jīng)介紹過被聲明為static的成員變量的值可以被本類或其他類的對象共享),將上述代碼改寫為以下形式。【例7.13】在項目中創(chuàng)建CopyOfTransferProperty類,該類舉例說明對象如何調用靜態(tài)成員變量。publicclassCopyOfTransferProperty{staticinti=47;//定義靜態(tài)成員變量publicvoidcall(){//定義成員方法System.out.println("調用call()方法");for(i=0;i<3;++){System.out.print(i+"");if(i==2){System.out.println("\n");}}}publicCopyOfTransferProperty(){//定義構造方法}publicstaticvoidmain(String[]args){//定義主方法CopyOfTransferPropertyt1=newCopyOfTransferProperty();//創(chuàng)建一個對象CopyOfTransferPropertyt2=newCopyOfTransferProperty();//創(chuàng)建另一個對象t2.i=60;//將類成員變量賦值為60//使用第一個對象調用類成員變量System.out.println("第一個實例對象調用變量i的結果:"+t1.1++);t1.call();//使用第一個對象調用類成員方法//使用第二個對象調用類成員變量System.out.println("第二個實例對象調用變量i的結果:"+t2.i);t2.call();//使用第二個對象調用類成員方法}}其運行結果如下:第一個實例對象調用變量i的結果:60調用call()方法012第二個實例對象調用變量i的結果:3調用call()方法012從上述運行結果中可以看到,由于使用“t2.i=60;”語句改變了靜態(tài)成員變量的值,使用對象t1調用成員變量的值也為60,這正是i值被定義為靜態(tài)成員變量的功效,即使使用兩個對象對同一個靜態(tài)成員變量進行操作,依然可以改變靜態(tài)成員變量的值,因為在內(nèi)存中兩個對象同時指向同一塊內(nèi)存區(qū)域。“t1.i++;”語句執(zhí)行完畢后,i值變?yōu)?.當再次調用call()方法時又被重新賦值為0,做循環(huán)打印操作。7.3.3?對象的引用在Java語言中盡管一切都可以看作對象,但真正的操作表示符實質上是一個引用,那么引用究竟在Java語言中是如何體現(xiàn)的呢?其語法格式如下。類名對象引用名稱例如,一個Book類的引用可以使用如下的代碼實現(xiàn)。Bookbook;通常一個引用不一定需要有一個對象相關聯(lián)。引用與對象相關聯(lián)的語法如下:Bookbook=newBook();Book:類名。book:對象。new:創(chuàng)建對象操作符。7.3.4?對象的比較在Java語言中有兩種對象的比較方式,分別為“==”運算符與equals()方法。實質上這兩種方式有著本質區(qū)別,下面舉例說明?!纠?.14】在項目中創(chuàng)建Compare類,該類說明了“==”運算符與equals()方法的區(qū)別。publicclassCompare{publicstaticvoidmain(String[]args){Stringc1=newString("abc");//創(chuàng)建兩個String型對象引用Stringc2=newString("abc");Stringc3=c1;//將c1對象引用賦予c3System.out.println("c2==c3的運算結果為:"+(c2==c3));//使用"=="運算符比較c2與c3System.out.println("c2.equals(c3)的運算結果為:"+(c2.equals(c3)));//使用equals()方法比較c2與c3}}其運行結果如下:c2==c3的運算結果為:falsec2.equals(c3)的運算結果為:true從上述運行結果中可以看出,“==”運算符和equals()方法比較的內(nèi)容是不相同的。equals()方法是String類中的方法,它用于比較兩個對象引用所指的內(nèi)容是否相等;而“==”運算符比較的是兩個對象引用的地址是否相等。由于c1與c2是兩個不同的對象引用,兩者在內(nèi)存中的位置不同,而“Stringc3=c1;”語句將c1的引用賦給c3,所以c1與c3這兩個對象引用是相等的,也就是打印c1==c3這樣的語句將返回true值。對象c1、c2、c3在內(nèi)存中的布局如圖7-12所示。圖7-12對象c1、c2、c3在內(nèi)存中的布局7.3.5?對象的銷毀每個對象都有生命周期,當對象的生命周期結束時,分配給該對象的內(nèi)存地址將會被回收,在其他語言中需要手動回收廢棄的對象,但是Java語言擁有一套完整的垃圾回收機制,用戶不必擔心廢棄的對象占用內(nèi)存,垃圾回收器將回收無用的占用內(nèi)存的資源。在談到垃圾回收機制之前,讀者首先需要了解哪一種對象會被Java虛擬機視為垃圾,其主要包括以下兩種情況。(1)對象引用超過其作用范圍,則這個對象將被視為垃圾。{Examplee=newExample();//對象e超過其作用范圍,將消亡}(2)將對象賦值為null。{Examplee=newExample();//當對象被置為空,將消亡e=null;}雖然垃圾回收機制已經(jīng)很完善,但垃圾回收器只能回收那些由new操作符創(chuàng)建的對象,如果某些對象不是通過new操作符在內(nèi)存中獲取一塊內(nèi)存區(qū)域,這種對象可能不被垃圾回收機制所識別。在Java語言中提供了一個finalize()方法,這個方法是Object類的方法,它被聲明為protected,用戶可以在自己的類中定義這個方法。如果用戶在類中定義了finalize()方法,在垃圾回收時首先調用該方法,并且在下一次垃圾回收動作發(fā)生時,才能真正回收對象占用的內(nèi)存。由于垃圾回收不受人為控制,具體執(zhí)行時間也不確定,所以finalize()方法也就無法執(zhí)行。為此,Java提供了System.gc()方法強制啟動垃圾回收器。7.3.6?范例3:統(tǒng)計圖書數(shù)量在商品(類的實例)的銷售過程中,需要對銷售進行統(tǒng)計。本范例將在類的構造方法中增加計數(shù)器來實現(xiàn)該功能,其運行結果如下:售出圖書:《語文》售出圖書:《數(shù)學》售出圖書:《英語》售出圖書:《歷史》售出圖書:《生物》總計銷售了5本圖書?。?)在項目中創(chuàng)建Book類,在類中定義一個靜態(tài)的成員變量用于保存實例化的次數(shù)。在構造方法中實現(xiàn)計數(shù)器的功能,代碼如下:publicclassBook{privatestaticintcounter=0;//定義一個計數(shù)器publicBook(Stringtitle){System.out.println("售出圖書:"+title);//輸出書名counter++;//計數(shù)器加1}publicstaticintgetCounter(){//獲得計數(shù)器的結果returncounter;}}(2)在項目中創(chuàng)建Test類,在類的main()方法中創(chuàng)建Book類對象并輸出對象的個數(shù),代碼如下:publicclassTest{publicstaticvoidmain(String[]args){//創(chuàng)建書名數(shù)組String[]titles={"《語文》","《數(shù)學》","《英語》","《歷史》","《生物》"};for(inti=0;i<5;i++){newBook(titles[newRandom().nextlnt(3)]);//利用書名數(shù)組創(chuàng)建Book對象}System,out.println("總計銷售了"+Book.getCounter()+"本圖書!");//輸出創(chuàng)建對象的個數(shù)}}7.3.7?范例4:重新計算對象的哈希碼Java語言中創(chuàng)建的對象是保存在堆中的,為了提高查找的速度而使用了散列查找。散列查找的基本思想是定義一個鍵來映射對象所在的內(nèi)存地址。當需要查找對象時,直接查找鍵就可以了,這樣就不用遍歷整個堆來查找對象了。本范例將查看不同對象的散列值,其運行結果如下:貓咪1號的哈希碼:849794130貓咪2號的哈希碼:1119356584貓咪3號的哈希碼:849794130貓咪1號是否與貓咪2號相同:false貓咪1號是否與貓咪3號相同:true(1)在項目中創(chuàng)建Cat類,在類中定義4個成員變量,分別表示貓咪的名字、年齡、重量和顏色,并提供構造方法來設置這些屬性值。本類的重點內(nèi)容在于重寫equals()方法和hashCode()方法,重寫equals()方法可以比較兩個對象是否相同,重寫hashCode()方法可以讓相同的對象保存在相同的位置。代碼如下:publicclassCat{privateStringname;//表示貓咪的名字privateintage;//表示貓咪的年齡privatedoubleweight;//表示貓咪的重量privateColorcolor;//表示貓咪的顏色publicCat(Stringname,intage,doubleweight,Colorcolor){//初始化貓咪的屬性this.narme=name;this.age=age;this,.weight=weight;this.color=color;}@Overridepublicbooleanequals(Objectobj){//利用屬性來判斷貓咪是否相同if(this==obj){//如果兩個貓咪是同一個對象則相同returntrue;}if(obj==null){//如果兩個貓咪有一個為null則不同returnfalse;}if(getClass()!=obj.getClass()){//如果兩個貓咪的類型不同則不同returnfalse;}Catcat=(Cat)obj;returnname.equals()&&(age==cat.age)&&(weight==cat.weight)&&(color.equals(cat.color));//比較貓咪的屬性}@OverridrpublicinthashCode(){//重寫hashCode()方法return7*name.hashCode()+11*newInteger(age).hashCode()+13*newDouble(weight).hashCode()+17*color.hashCode();}}(2)在com.mingrisoft包中創(chuàng)建類文件,名稱為Test。在該類的main()方法中創(chuàng)建3只貓咪,并將它們初始化,然后輸出貓咪的哈希碼和比較的結果。代碼如下:publicclassTest{publicstaticvoidmain(String[]args){Catcat1=newCat("Java",12,21,Color.BLACK);//創(chuàng)建貓咪1號Catcat2=newCat("C++",12,21,Color.WHITE);//創(chuàng)建貓咪2號Catcat3=newCat("Java",12,21,Color.BLACK);//創(chuàng)建貓咪3號System.out.println("貓咪1號的哈希碼:"+cat1.hashCode());//

溫馨提示

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

最新文檔

評論

0/150

提交評論