面向?qū)ο缶幊蘝第1頁(yè)
面向?qū)ο缶幊蘝第2頁(yè)
面向?qū)ο缶幊蘝第3頁(yè)
面向?qū)ο缶幊蘝第4頁(yè)
面向?qū)ο缶幊蘝第5頁(yè)
已閱讀5頁(yè),還剩100頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

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

文檔簡(jiǎn)介

1、第4章 面向?qū)ο缶幊?.1 面向?qū)ο蠡靖拍?.2 Java的類(lèi)與對(duì)象4.3 成員變量與封裝4.4 成員方法習(xí)題現(xiàn)實(shí)世界中,對(duì)象(object)是狀態(tài)(屬性)和行為的結(jié)合體,對(duì)象隨處可見(jiàn)。對(duì)象普遍具有的特征是狀態(tài)和行為。在開(kāi)發(fā)軟件的信息世界中,對(duì)象定義為相關(guān)數(shù)據(jù)和方法的集合。對(duì)象是現(xiàn)實(shí)世界對(duì)象的抽象模型。從現(xiàn)實(shí)世界對(duì)象中抽象出來(lái)的對(duì)象使用數(shù)據(jù)和方法描述其在現(xiàn)實(shí)世界中的狀態(tài)和行為特征,一般通過(guò)變量描述其狀態(tài),通過(guò)方法實(shí)現(xiàn)其行為。變量是一種有名稱(chēng)的數(shù)據(jù)實(shí)體,而方法則是和對(duì)象相關(guān)的函數(shù)或過(guò)程。4.1 面向?qū)ο蠡靖拍?4.1.1 對(duì)象 信息世界中的對(duì)象不僅可以表達(dá)現(xiàn)實(shí)世界中的具體對(duì)象,如在動(dòng)畫(huà)程序里

2、用一個(gè)小狗模型代表現(xiàn)實(shí)世界里的小狗,還可以表達(dá)現(xiàn)實(shí)世界中的一些抽象概念,例如圖形用戶(hù)界面的窗口就是一個(gè)抽象概念的對(duì)象,它具有大小等狀態(tài)數(shù)據(jù),還具有打開(kāi)、運(yùn)動(dòng)等行為方法。如果給定了動(dòng)畫(huà)程序里小狗的名字、形狀、移動(dòng)速度和移動(dòng)方法,就有了一個(gè)確定的對(duì)象,稱(chēng)為實(shí)例對(duì)象。相應(yīng)地,和一個(gè)實(shí)例對(duì)象相關(guān)的變量稱(chēng)為實(shí)例變量,相關(guān)的方法稱(chēng)為實(shí)例方法。封裝的含義是把類(lèi)設(shè)計(jì)成一個(gè)黑箱,使用者只能看見(jiàn)類(lèi)中定義的公共方法,而看不到方法實(shí)現(xiàn)的細(xì)節(jié),也不能直接對(duì)類(lèi)的數(shù)據(jù)進(jìn)行操作,迫使用戶(hù)通過(guò)接口去訪問(wèn)數(shù)據(jù),這種封裝正是面向?qū)ο缶幊淘O(shè)計(jì)者追求的理想境界。相關(guān)數(shù)據(jù)和方法封裝到一個(gè)包里,為程序員帶來(lái)了兩個(gè)好處: 模塊化和數(shù)據(jù)隱藏。

3、模塊化意味著對(duì)象源代碼的編寫(xiě)和維護(hù)可以獨(dú)立進(jìn)行,不會(huì)影響到其他模塊,而且有很好的重用性。數(shù)據(jù)隱藏則使對(duì)象有能力保護(hù)自己,對(duì)象提供一個(gè)公共接口和其他對(duì)象聯(lián)系,自行維護(hù)自身的數(shù)據(jù)和方法而不影響所有依賴(lài)于它的對(duì)象。 4.1.2 封裝 單獨(dú)一個(gè)對(duì)象是沒(méi)有什么作用的,多個(gè)對(duì)象聯(lián)系在一起才會(huì)有完整的功能。對(duì)象之間的相互聯(lián)系和相互作用是靠消息(message)的傳遞完成的。在下面的例4.1中可以看出,單擊“相加”按鈕,一個(gè)事件消息就傳遞給事件監(jiān)聽(tīng)者對(duì)象。事件監(jiān)聽(tīng)者對(duì)象調(diào)用相應(yīng)的事件處理方法進(jìn)行響應(yīng),最后將處理結(jié)果以消息的形式傳遞給文本域?qū)ο?。文本域?qū)ο笥米陨淼姆椒ń邮障?,并將結(jié)果顯示出來(lái)。由此看出,對(duì)象的

4、行為由方法來(lái)實(shí)現(xiàn),消息傳遞是對(duì)象之間進(jìn)行交互的主要方式。構(gòu)成消息的3個(gè)要素是: 接收消息的對(duì)象、接收消息后進(jìn)行處理的方法和方法所需要的參數(shù)。 4.1.3 消息 現(xiàn)實(shí)世界中有很多同類(lèi)對(duì)象。例如,你的自行車(chē)是千千萬(wàn)萬(wàn)輛自行車(chē)中的一個(gè),用面向?qū)ο缶幊绦g(shù)語(yǔ)說(shuō),是自行車(chē)類(lèi)的一個(gè)實(shí)例。自行車(chē)類(lèi)有很多共同特征(狀態(tài)和行為),但你的自行車(chē)和其他自行車(chē)是有區(qū)別的。基于同樣道理,面向?qū)ο缶幊炭偨Y(jié)對(duì)象的特征設(shè)計(jì)成類(lèi)(class)。類(lèi)就是對(duì)象的軟件圖紙、模板或原型,它定義了同類(lèi)對(duì)象共有的變量和方法。例如,自行車(chē)類(lèi)定義了自行車(chē)必須有的狀態(tài)和行為: 車(chē)輪、變速器、剎車(chē)器、如何驅(qū)動(dòng)、如何變速、如何剎車(chē)等。你可以用它生成一個(gè)

5、有特定狀態(tài)和方法的實(shí)例,別人也可以用它生成一個(gè)屬于自己的實(shí)例。4.1.4 類(lèi) 對(duì)象和類(lèi)的描述盡管十分相似,但它們還是有區(qū)別的?,F(xiàn)實(shí)世界中,類(lèi)不能代表它所描述的對(duì)象,這是非常清楚的,因?yàn)樽孕熊?chē)圖紙畢竟不是自行車(chē)。但在軟件業(yè)中二者不太容易區(qū)分。一方面,由于軟件對(duì)象都是現(xiàn)實(shí)對(duì)象或抽象概念的電子模型;另一方面,經(jīng)常不加區(qū)分地將對(duì)象和類(lèi)統(tǒng)稱(chēng)為“對(duì)象”。Java編程就是設(shè)計(jì)類(lèi),可以采用自定義方法或繼承方法設(shè)計(jì)一個(gè)類(lèi),然后使用它的實(shí)例對(duì)象完成具體的功能。 面向?qū)ο缶幊淘试S用一個(gè)類(lèi)定義另外一個(gè)類(lèi)。子類(lèi)繼承了父類(lèi)的狀態(tài)和行為,但并不局限于此。也就是說(shuō),子類(lèi)可以添加新的變量和方法,有自己的特點(diǎn)。子類(lèi)還可以覆蓋(o

6、verride)繼承下來(lái)的方法,實(shí)現(xiàn)特殊要求。4.1.5 繼承 繼承(inheritance)不但可以發(fā)生在同一個(gè)層次上,也可以發(fā)生在不同層次上。這種繼承形成了一棵倒置的樹(shù),從根部開(kāi)始發(fā)芽分支,長(zhǎng)成一棵繼承樹(shù)。在Java系統(tǒng)中這棵樹(shù)的根就是Object類(lèi),所有層次的類(lèi)都是從Object類(lèi)那里直接或間接地衍生下來(lái)的。Object僅提供了所有的類(lèi)在Java虛擬機(jī)上運(yùn)行時(shí)所需要的基本狀態(tài)和方法。一般來(lái)說(shuō),層次越高,類(lèi)就越抽象,反之類(lèi)就越具體。繼承使父類(lèi)的代碼得到重用,在繼承父類(lèi)提供的共同特性基礎(chǔ)上添加新的代碼,使編程不必一切都從頭開(kāi)始,提高了編程效率。 接口(interface)可以看成是為兩個(gè)不相

7、關(guān)的實(shí)體提供交流途徑的設(shè)備。在Java中,接口就是為兩個(gè)不相關(guān)的類(lèi)提供交流的設(shè)備。接口非常類(lèi)似于協(xié)議(protocol,一種共同行為的約定),是一個(gè)包含方法定義和常量值的集合。Java不支持多繼承,子類(lèi)只能有一個(gè)父類(lèi)。有時(shí)需要使用其他類(lèi)中的方法,但又無(wú)法直接繼承,在這種情況下,可以使用接口技術(shù)。例如,Java的事件單獨(dú)放在一個(gè)事件類(lèi)中,子類(lèi)一般不直接從這個(gè)事件類(lèi)派生,而由Applet類(lèi)派生,但子類(lèi)運(yùn)行時(shí)需要響應(yīng)各種事件,則需要使用事件類(lèi)的處理方法。4.1.6 接口 子類(lèi)不能既從父類(lèi)Applet類(lèi)繼承又從事件類(lèi)繼承,要同時(shí)使用二者的方法,就要使用接口。接口不需要建立繼承關(guān)系,就可以使兩個(gè)不相關(guān)的

8、類(lèi)進(jìn)行交互。接口提取了類(lèi)的某些共同點(diǎn),聲明一些能被多個(gè)類(lèi)實(shí)現(xiàn)的方法,但不給出方法體。接口由類(lèi)的聲明語(yǔ)句中的implements關(guān)鍵字引入,并在類(lèi)體中實(shí)現(xiàn)接口的方法。例如在類(lèi)的聲明語(yǔ)句中“class Frame1 extends Frame implements ActionListener”實(shí)現(xiàn)ActionListener接口。 例4.1 設(shè)計(jì)一個(gè)Applet小程序,使其可以進(jìn)行簡(jiǎn)單的加法運(yùn)算。/ 源程序名: Addition.javaimport java.awt.*;import java.awt.event.*;import java.applet.Applet;public class

9、 Addition extends Applet implements ActionListener Label label1=new Label(+); Label label2=new Label(=); TextField field1=new TextField(6); TextField field2=new TextField(6); TextField field3=new TextField(6); Button button1=new Button(相加); public void init() / 初始化 add(field1); add(label1); add(fiel

10、d2); add(label2); add(field3); add(button1); button1.addActionListener(this); public void actionPerformed(ActionEvent e) / 處理按鈕事件 int x=Integer.parseInt(field1.getText()+Integer.parseInt(field2.getText(); field3.setText(Integer.toString(x); / 數(shù)值轉(zhuǎn)換為字符串 為了瀏覽Applet應(yīng)用程序,還需要建立一個(gè)HTML文本文件。在記事本中編寫(xiě)以下語(yǔ)句,并存為名稱(chēng)

11、為AP1.HTML的文本文件。先將Addition.java源程序編譯為Addition.class,然后使用瀏覽器或使用小程序查看器瀏覽,即在命令提示符下輸入: appletviewer AD1.HTML,運(yùn)行結(jié)果如圖4.1所示。 圖 4.1現(xiàn)在讓我們使用面向?qū)ο蟮乃枷雭?lái)分析一下Addition.java源程序的結(jié)構(gòu)。前面3行是說(shuō)明語(yǔ)句,分別引入Java系統(tǒng)包awt和applet。語(yǔ)句import java.applet.Applet引入了applet包中的Applet類(lèi);語(yǔ)句import java.awt.* 引入了awt包中的所有類(lèi);語(yǔ)句import java.awt.event.* 引

12、入了awt的event包的所有類(lèi)。 Java系統(tǒng)包提供了很多預(yù)定義類(lèi),如Applet類(lèi),可以直接引用而不必從頭開(kāi)始編寫(xiě)程序。因?yàn)槔?.1編寫(xiě)的程序是一個(gè)Applet應(yīng)用程序,所以一定要引入Applet類(lèi),以便使用其定義好的各種數(shù)據(jù)和方法。又由于程序中需要使用圖形界面,要使用文本框和按鈕,所以還需要加載Java系統(tǒng)包awt,awt中包含了所有處理圖形界面的類(lèi)。在執(zhí)行加法運(yùn)算需要單擊“相加”按鈕,這會(huì)產(chǎn)生一個(gè)鼠標(biāo)事件或鍵盤(pán)事件,因此還要引入專(zhuān)門(mén)處理各種事件的event包。第4行開(kāi)始是程序的主體,聲明了Addition類(lèi),它繼承自Applet類(lèi)。繼承不是目的而是一種手段,作為Applet的一個(gè)子類(lèi),

13、具有Applet的共性。繼承的狀態(tài)和方法往往不足以實(shí)現(xiàn)程序的要求,必須根據(jù)題目的具體要求,由用戶(hù)添加各種對(duì)象和方法,改造成滿(mǎn)足題目要求的程序。Java編程就是基于這樣的思想。第4行是類(lèi)聲明語(yǔ)句public class Addition extends Applet implements ActionListener 說(shuō)明Addition是繼承自Applet的公共子類(lèi),并建立了一個(gè)單擊事件監(jiān)聽(tīng)器ActionListener接口,在程序運(yùn)行時(shí)可監(jiān)聽(tīng)發(fā)生了什么事件,并負(fù)責(zé)調(diào)用相應(yīng)的事件處理方法作出響應(yīng)。這個(gè)框架出來(lái)后,剩下的任務(wù)就是設(shè)計(jì)成員變量和成員方法了。第510行聲明了Addition類(lèi)的6個(gè)對(duì)

14、象數(shù)據(jù)。兩個(gè)標(biāo)簽對(duì)象用于顯示運(yùn)算符號(hào);3個(gè)文本域?qū)ο笥糜诮邮苡脩?hù)的輸入;一個(gè)按鈕對(duì)象用于執(zhí)行加法運(yùn)算。第11行到19行是Addition類(lèi)的方法init的聲明和實(shí)現(xiàn)語(yǔ)句。類(lèi)中所有的對(duì)象行為都由這個(gè)類(lèi)來(lái)控制,這種控制是通過(guò)改造繼承下來(lái)的init方法實(shí)現(xiàn)的。類(lèi)所包含的方法相當(dāng)于傳統(tǒng)編程語(yǔ)言的過(guò)程或函數(shù),可完成一定的功能。init是一個(gè)不需要返回值的方法,init方法屬于Applet,Addition對(duì)它進(jìn)行了修改,由它實(shí)現(xiàn)將上面添加的各個(gè)對(duì)象加入到Addition的顯示區(qū),并給按鈕對(duì)象注冊(cè)事件監(jiān)聽(tīng)器(Addition)。第20行到23行是actionPerformed事件處理方法的聲明和實(shí)現(xiàn)語(yǔ)句。

15、事件監(jiān)聽(tīng)器和按鈕對(duì)象之間通過(guò)監(jiān)聽(tīng)接口建立起消息通道,一旦按鈕被單擊,該事件的消息就會(huì)傳遞給監(jiān)聽(tīng)器。監(jiān)聽(tīng)器收到事件消息后,負(fù)責(zé)調(diào)用事件處理方法actionPerformed來(lái)響應(yīng)執(zhí)行處理方法。本例中的按鈕事件處理方法就是將用戶(hù)輸入的兩個(gè)數(shù)轉(zhuǎn)換成整數(shù)后相加,然后顯示在第三個(gè)文本域。Java程序的所有數(shù)據(jù)類(lèi)型都是用類(lèi)來(lái)實(shí)現(xiàn)的,Java語(yǔ)言是建立在類(lèi)這個(gè)邏輯結(jié)構(gòu)之上,所以Java是一種完全面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言。類(lèi)是Java的核心,Java程序都由類(lèi)組成,一個(gè)程序至少要包含一個(gè)類(lèi),也可以包含多個(gè)類(lèi)。對(duì)象是類(lèi)的實(shí)例,Java程序中可以使用標(biāo)識(shí)符表示對(duì)象,并通過(guò)對(duì)象引用類(lèi)中的變量和方法。Java程序員的任

16、務(wù)就是設(shè)計(jì)出類(lèi)和對(duì)象來(lái)解決實(shí)際問(wèn)題。創(chuàng)建類(lèi)時(shí)既可以從父類(lèi)繼承,也可以自行定義。 4.2 Java的類(lèi)與對(duì)象 類(lèi)通過(guò)關(guān)鍵字class來(lái)創(chuàng)建,下面的聲明語(yǔ)句格式給出了可能出現(xiàn)的符號(hào)和順序: public abstract final extends 父類(lèi) implements 接口 4.2.1 類(lèi)的創(chuàng)建 1. class(類(lèi)名)class關(guān)鍵字告訴編譯器這是一個(gè)類(lèi),類(lèi)名是可以自由選取但必須是合法的標(biāo)識(shí)符。在聲明類(lèi)的語(yǔ)句中,class前面的關(guān)鍵字稱(chēng)為類(lèi)的修飾符。 2. public(公共的)在沒(méi)有任何修飾符的默認(rèn)情況下,類(lèi)只能被同一個(gè)源程序文件或同一個(gè)包中的其他類(lèi)使用。加上public修飾符后,類(lèi)可

17、以被任何包中的類(lèi)使用,稱(chēng)為公共類(lèi)。有關(guān)包的概念請(qǐng)參考后面章節(jié)的內(nèi)容(目前可把包當(dāng)作一組相關(guān)源程序文件)。注意: 在同一個(gè)源程序文件中不能出現(xiàn)兩個(gè)以上的public類(lèi),否則編譯器會(huì)告訴你將第二個(gè)public類(lèi)放在另一個(gè)文件中。 3. abstract(抽象的)有時(shí),定義的類(lèi)代表了一個(gè)抽象的概念,就不能用它來(lái)實(shí)例化一個(gè)對(duì)象。同樣在面向?qū)ο缶幊讨?,可能建立了一個(gè)不需要產(chǎn)生對(duì)象的類(lèi)。例如,java.lang包中的Number類(lèi)代表了數(shù)這個(gè)抽象概念,可以用它在程序中產(chǎn)生一個(gè)數(shù)的子類(lèi),如Integer或Float,但從Number中直接生成對(duì)象是沒(méi)有意義的。abstract說(shuō)明的類(lèi)稱(chēng)為抽象類(lèi),不能用它實(shí)例

18、化一個(gè)對(duì)象,它只能被繼承。 4. final(最終的)final說(shuō)明的類(lèi)稱(chēng)為最終類(lèi)。一個(gè)最終類(lèi)不可能有子類(lèi),也就是說(shuō)它不能被繼承。把一個(gè)類(lèi)說(shuō)明為最終類(lèi)有兩點(diǎn)理由: 為了提高系統(tǒng)的安全性和出于對(duì)一個(gè)完美類(lèi)的偏愛(ài)。黑客常用的一個(gè)攻擊技術(shù)是設(shè)計(jì)一個(gè)子類(lèi),然后用它替換原來(lái)的父類(lèi)。為防止這樣的事情發(fā)生,可以把類(lèi)聲明為最終類(lèi),不讓黑客有機(jī)可乘。Java中的String類(lèi)設(shè)計(jì)為一個(gè)最終類(lèi)就是出于這樣的目的。此外,程序員有時(shí)也會(huì)把一些無(wú)懈可擊的類(lèi)聲明成最終類(lèi),不讓別人把它們改得面目全非。注意: final和abstract不能同時(shí)修飾一個(gè)類(lèi),這樣的類(lèi)是沒(méi)有意義的。 5. extends(繼承)父類(lèi)名exten

19、ds告訴編譯器創(chuàng)建的類(lèi)是從父類(lèi)繼承下來(lái)的子類(lèi),父類(lèi)必須是Java系統(tǒng)類(lèi)或已經(jīng)定義的類(lèi)。從父類(lèi)繼承,可以提高代碼的重用性,不必從頭開(kāi)始設(shè)計(jì)程序。大部分情況下應(yīng)該利用繼承的手段編程,只在沒(méi)有合適的類(lèi)可以繼承時(shí)才自己設(shè)計(jì)類(lèi)。 6. implements(實(shí)現(xiàn))接口名implements告訴編譯器類(lèi)實(shí)現(xiàn)的接口,接口必須有定義,一般為系統(tǒng)類(lèi)。接口是消息傳遞的通道,通過(guò)接口,消息才能傳遞到處理方法中進(jìn)行處理。implements說(shuō)明你的類(lèi)可以實(shí)現(xiàn)的一個(gè)或多個(gè)接口,如果有多個(gè)接口,要用逗號(hào)分隔。例4.2 下面這個(gè)Applet程序?qū)⒃陧?yè)面上輸出兩個(gè)矩形,并伴有文字輸出,如圖4.2所示。import java.

20、awt.*;import java.applet.Applet;public class Class1 extends Applet private int x, y, width, height; public void init() width=60; height=60; public void setPosition(int xPos, int yPos) x=xPos; y=yPos; public void paint(Graphics g) setPosition(20,20); g.drawRect(x, y, width, height); g.drawString(矩形 1

21、 的 X 位置: +x, 20,100); g.drawString(矩形 1 的 Y 位置: +y, 20,120); setPosition(170,20); g.drawRect(x, y, width, height); g.drawString(矩形 2 的 X 位置: +x, 170,100); g.drawString(矩形 2 的 Y 位置: +y, 170,120); 圖 4.2 程序中創(chuàng)建的Class1類(lèi)是一個(gè)繼承系統(tǒng)類(lèi)Applet的子類(lèi)。一般來(lái)說(shuō),用繼承的方式創(chuàng)建一個(gè)類(lèi)是最常用也是最簡(jiǎn)單的方法,子類(lèi)除了可以直接使用父類(lèi)的數(shù)據(jù)和方法外,還可以有自己的數(shù)據(jù)和方法。在Class

22、1中添加了4個(gè)數(shù)據(jù),用來(lái)確定一個(gè)矩形的4個(gè)參數(shù)。在paint方法中,先調(diào)用setPosition方法設(shè)定矩形的位置,然后用Graphics圖形類(lèi)的drawRect方法畫(huà)出矩形。g是一個(gè)圖形對(duì)象,是Graphics圖形類(lèi)的實(shí)例對(duì)象,由Applet啟動(dòng)時(shí)通過(guò)paint(Graphics g)方法傳遞過(guò)來(lái)的,所以對(duì)象g可以直接使用圖形類(lèi)的方法。最后,上面的例子可以采用更簡(jiǎn)單的方法來(lái)編程。 類(lèi)是對(duì)象的產(chǎn)品模板。在現(xiàn)實(shí)世界里,我們使用的是產(chǎn)品而不是產(chǎn)品的圖紙。同樣道理,Java運(yùn)行的應(yīng)該是用類(lèi)創(chuàng)建的實(shí)例化對(duì)象。一個(gè)典型的Java程序會(huì)創(chuàng)建很多對(duì)象,它們通過(guò)消息傳遞進(jìn)行相互交流,共同完成程序的功能。一旦任

23、務(wù)完成,對(duì)象就會(huì)被垃圾收集器收回,完成它從創(chuàng)建、使用到清除的生命三步曲。下面介紹對(duì)象的創(chuàng)建過(guò)程。4.2.2 對(duì)象的創(chuàng)建 例4.3 下面這個(gè)程序是改寫(xiě)例4.2得到的,輸出結(jié)果如圖4.2所示。import java.awt.*;import java.applet.Applet;public class Class2 extends Applet MyBox b1=new MyBox(); MyBox b2=new MyBox(170,20,60,60); public void paint(Graphics g) b1.setPosition(20,20); b1.setSize(60,60);

24、 b1.draw(g); g.drawString(矩形 1 的 X 位置: +b1.getX(), 20, 100); g.drawString(矩形 1 的 Y 位置: +b1.getY(), 20, 120); b2.draw(g); g.drawString(矩形 2 的 X 位置: +b2.getX(), b2.getX(), b2.getY()+80); g.drawString(矩形 2 的 Y 位置: +b2.getY(), b2.getX(), b2.getY()+100); class MyBox private int x, y, width, height; MyBox

25、() x=0; y=0; width=0; height=0; MyBox(int xPos, int yPos, int w, int h) x=xPos; y=yPos; width=w; height=h; public void setPosition (int xPos, int yPos) x=xPos; y=yPos; public void setSize (int w, int h) width=w; height=h; public int getX() return x; public int getY() return y; public void draw(Graph

26、ics g) g.drawRect(x, y, width, height); 例4.3更具面向?qū)ο缶幊田L(fēng)格。Class2和例4.2的Class1同屬一類(lèi),但做的事情更少。Class2使用new操作符創(chuàng)建了兩個(gè)對(duì)象實(shí)例b1和b2。它們由自定義類(lèi)MyBox產(chǎn)生,然后在paint方法中向它們傳遞信息,操縱這兩個(gè)對(duì)象完成給定的任務(wù)。MyBox是自定義類(lèi),雖然沒(méi)有明確指出其父類(lèi),但仍存在繼承關(guān)系,它的父類(lèi)就是Java的根類(lèi)Object。每一種面向?qū)ο缶幊陶Z(yǔ)言都有一個(gè)這樣的根類(lèi),然后衍生出該語(yǔ)言的系統(tǒng)類(lèi)。自定義類(lèi)需要自行設(shè)計(jì)類(lèi)的狀態(tài)和行為,即確定它的成員變量和方法。從例4.3中可以看出,程序的paint

27、方法主要使用對(duì)象b1、b2和g來(lái)完成具體的功能。下面給出創(chuàng)建對(duì)象和使用對(duì)象的方法說(shuō)明。 1. 創(chuàng)建對(duì)象與構(gòu)造方法首先必須擁有一個(gè)合適的類(lèi)才能創(chuàng)建一個(gè)合適的對(duì)象,有了合適的對(duì)象才能完成合適的工作。下面的3條語(yǔ)句分別創(chuàng)建了3個(gè)對(duì)象: Lable label1=new Label(標(biāo)簽);TextField field1=new TextField(10);MyBox b1=new MyBox(20,20,100,100);new稱(chēng)為操作符,用于對(duì)象的實(shí)例化,負(fù)責(zé)調(diào)用類(lèi)的構(gòu)造方法初始化創(chuàng)建的對(duì)象,經(jīng)過(guò)上面的創(chuàng)建,每個(gè)對(duì)象就可以被使用了。歸納總結(jié)可知,創(chuàng)建對(duì)象語(yǔ)句有3個(gè)組成部分: 聲明對(duì)象、實(shí)例化、初

28、始化。格式為: =new (參數(shù)列表)其中參數(shù)列表可能是可選的。如: MyBox b2=new MyBox(20,20,100,100);MyBox b1=new MyBox( );創(chuàng)建對(duì)象相當(dāng)于定義一個(gè)變量,既可采用上述方法,也可以把上述步驟分開(kāi)進(jìn)行,先聲明對(duì)象,再實(shí)例化對(duì)象,進(jìn)行初始化。(1) 聲明對(duì)象 如: MyBox b2(2) 實(shí)例化= new (參數(shù)列表)如,MyBox b2=new MyBox(20,20,100,100);實(shí)例化由new操作符實(shí)現(xiàn),實(shí)例化就是為對(duì)象分配內(nèi)存。new操作符需要一個(gè)參數(shù),就是類(lèi)的構(gòu)造方法,構(gòu)造方法是用于初始化對(duì)象的特別方法。構(gòu)造方法與類(lèi)同名如MyBo

29、x,由new操作符根據(jù)類(lèi)名決定為新建對(duì)象分配多大的內(nèi)存。 2. 對(duì)象初始化的說(shuō)明(1) 系統(tǒng)對(duì)變量的初始化前面介紹變量時(shí)說(shuō)明,如果變量聲明后沒(méi)有賦值,在使用變量時(shí)會(huì)出現(xiàn)錯(cuò)誤。當(dāng)用new創(chuàng)建了一個(gè)對(duì)象時(shí),系統(tǒng)會(huì)為對(duì)象中的變量進(jìn)行初始化。即不但為變量分配相應(yīng)的存儲(chǔ)單元,還設(shè)置相應(yīng)初值。系統(tǒng)為byte、short、int、long類(lèi)型變量設(shè)置初值為0;float類(lèi)型變量初值為0.0f;double類(lèi)型變量初值為0.0;char字符型變量為u0000;boolean邏輯變量初值為false;引用類(lèi)型初值為null。(2) 構(gòu)造方法的作用與構(gòu)成構(gòu)造方法對(duì)于類(lèi)是十分重要的,new操作符為對(duì)象分配內(nèi)存后將調(diào)

30、用類(lèi)的構(gòu)造方法確定對(duì)象的初始狀態(tài),初始化所有變量。也就是說(shuō),對(duì)象的初始化任務(wù)要靠構(gòu)造方法來(lái)完成。如何定義構(gòu)造方法呢?即在構(gòu)造方法中對(duì)類(lèi)的成員變量定義賦值的方式。例如例4.3中定義的兩個(gè)構(gòu)造方法: MyBox() x=0; y=0; width=0; height=0; MyBox(int xPos, int yPos, int Width, int Height) x=xPos; y=yPos; width=Width; height=Height;MyBox() 和MyBox(int, int, int, int) 同為類(lèi)MyBox的構(gòu)造方法,方法名相同而參數(shù)不同,這是類(lèi)的多態(tài)性的體現(xiàn)。程序

31、可以根據(jù)參數(shù)的不同,自動(dòng)調(diào)用正確的構(gòu)造方法。不同的構(gòu)造方法可以為程序員提供更加靈活的選擇。注意: 構(gòu)造方法的名稱(chēng)和類(lèi)同名,沒(méi)有返回類(lèi)型。盡管構(gòu)造方法看起來(lái)和一般的成員方法沒(méi)有差別,但它不是方法,也不是類(lèi)的成員。因此,構(gòu)造方法不能由程序直接調(diào)用,只能由new操作符調(diào)用。在同一個(gè)類(lèi)中可以定義多個(gè)構(gòu)造方法,名字相同而參數(shù)可以不同。它們是以參數(shù)的個(gè)數(shù)來(lái)區(qū)分的,這種情況稱(chēng)為方法重載(overload)。創(chuàng)建對(duì)象時(shí),程序員可根據(jù)需要選擇合適的構(gòu)造方法。對(duì)于簡(jiǎn)單的自定義類(lèi),可以不設(shè)計(jì)構(gòu)造方法,在聲明變量的同時(shí)賦值,那么創(chuàng)建對(duì)象時(shí),會(huì)使用默認(rèn)構(gòu)造方法。默認(rèn)的構(gòu)造方法沒(méi)有參數(shù),屬于父類(lèi),如果父類(lèi)中沒(méi)有提供構(gòu)造方

32、法,將產(chǎn)生編譯錯(cuò)誤。例如,第2章介紹的簡(jiǎn)單數(shù)據(jù)類(lèi)型就是在聲明變量時(shí)同時(shí)賦值的,其實(shí)是使用了父類(lèi)提供的構(gòu)造方法。如,實(shí)現(xiàn)整型操作的Integer類(lèi),其構(gòu)造方法的參數(shù)有兩種形式: Integer i=new Integer(256);/以一個(gè)int參數(shù)值創(chuàng)建一個(gè)Integer對(duì)象Integer i=new Integer(256);/ 以一個(gè)string參數(shù)值創(chuàng)建一個(gè)Integer對(duì)象如果初始化時(shí)還要執(zhí)行一些其他命令,就必須設(shè)計(jì)構(gòu)造方法,將這些命令放在構(gòu)造方法中,因?yàn)镴ava規(guī)定命令語(yǔ)句不能出現(xiàn)在類(lèi)體中,只能放在方法中。 3. 對(duì)象的使用對(duì)象被實(shí)例化后即可使用。通過(guò)對(duì)象可以引用類(lèi)的成員變量,通過(guò)對(duì)

33、象還可以調(diào)用類(lèi)的方法。創(chuàng)建對(duì)象時(shí),一個(gè)對(duì)象的所有變量和方法代碼(包含對(duì)象的類(lèi)的變量和方法)都被讀到專(zhuān)為它開(kāi)辟的內(nèi)存區(qū)域中。為了讓解釋器知道代碼的內(nèi)存地址,使用對(duì)象的任何成員時(shí)都要加上引用。即在變量和方法的前面加上對(duì)象名,并用圓點(diǎn)分隔。格式為: .如例4.3中通過(guò)b1.setPosition設(shè)定MyBox的位置,通過(guò)b1.setSize改變MyBox的大小,通過(guò)b1.getX和b1.getY獲取MyBox的位置。 4. 清除對(duì)象與垃圾收集機(jī)制Java引入了新的內(nèi)存管理機(jī)制,由Java虛擬機(jī)擔(dān)當(dāng)垃圾收集器的工作。你可以任意創(chuàng)建對(duì)象而不用擔(dān)心如何清除它們,垃圾收集器會(huì)自動(dòng)清除它們。使用new操作符創(chuàng)

34、建對(duì)象后,Java虛擬機(jī)自動(dòng)為該對(duì)象分配內(nèi)存并保持跟蹤。Java虛擬機(jī)能判斷出對(duì)象是否還被引用,對(duì)不再被引用的對(duì)象釋放其占用的內(nèi)存。這種定期尋找不再使用的對(duì)象并自動(dòng)釋放對(duì)象占用內(nèi)存的過(guò)程稱(chēng)為垃圾收集。Java虛擬機(jī)實(shí)際上是利用變量生存期來(lái)管理內(nèi)存的,對(duì)象的引用被保存在變量中,當(dāng)程序跳出變量所在的區(qū)域后,它就會(huì)被自動(dòng)清除。如果要明確地清除一個(gè)對(duì)象,可以自行清除它,只需把一個(gè)空值賦給這個(gè)對(duì)象引用即可。如: Rectangle r=new Rectangle(10,10,100,100);r=null;上述語(yǔ)句執(zhí)行后,r對(duì)象將被清除。Java的垃圾收集機(jī)制大大減輕了程序員的負(fù)擔(dān),不用再編寫(xiě)專(zhuān)門(mén)的內(nèi)存

35、回收程序解決內(nèi)存分配問(wèn)題。不僅提高了編程效率,而且進(jìn)一步增強(qiáng)了Java程序的穩(wěn)固性。通過(guò)上面3個(gè)程序的設(shè)計(jì),希望讀者理解面向?qū)ο缶幊痰幕靖拍睿?類(lèi)、對(duì)象、方法、抽象、封裝、繼承等。封裝是抽象的具體實(shí)現(xiàn)。封裝就是用操作方法把數(shù)據(jù)封閉到類(lèi)中,形成以數(shù)據(jù)為核心,以方法為外殼的類(lèi)。封裝能保護(hù)類(lèi)的數(shù)據(jù)免受外界的更改,消除由此帶來(lái)的對(duì)程序的不可知影響。封裝的結(jié)果是形成獨(dú)立的和完整的程序模塊,它們之間通過(guò)被授權(quán)的操作方法來(lái)傳遞消息,達(dá)到改變對(duì)象狀態(tài)的目的,這是提高程序健壯性的有力保證。封裝后的類(lèi)可以被繼承。成員變量描述了類(lèi)和對(duì)象的狀態(tài),有時(shí)也稱(chēng)為屬性、數(shù)據(jù)或域(field)。對(duì)成員變量的操作實(shí)際上就是改變

36、類(lèi)和對(duì)象的狀態(tài),使之能滿(mǎn)足程序的需要。與類(lèi)相似,成員變量也有很多修飾符,用來(lái)控制對(duì)成員變量的訪問(wèn),實(shí)現(xiàn)對(duì)類(lèi)和對(duì)象的封裝。 4.3 成員變量與封裝 成員變量的聲明必須放在類(lèi)體中,通常是在成員方法之前。在方法中聲明的變量不是成員變量,而是方法的局部變量,二者是有區(qū)別的。例4.4 顯示當(dāng)前日期和時(shí)間,運(yùn)行結(jié)果見(jiàn)圖4.3。圖 4.3 4.3.1 成員變量的聲明 例4.4 顯示當(dāng)前日期和時(shí)間,運(yùn)行結(jié)果見(jiàn)圖4.3。import java.awt.Graphics;import java.applet.Applet;import java.util.Calendar;class Time private C

37、alendar t; private int y, m, d, hh, mm, ss; Time () t=Calendar.getInstance(); y=t.get(t.YEAR); m=t.get(t.MONTH)+1; d=t.get(t.DATE); hh=t.get(t.HOUR_OF_DAY); mm=t.get(t.MINUTE); ss=t.get(t.SECOND); public String getDate() return y+ 年+m+月+d+日; public String getTime() String s=hh+ 時(shí)+mm+分+ss+秒; return s

38、; public class ShowTime extends Applet Time t=new Time(); public void paint(Graphics g) g.drawString(當(dāng)前日期: +t.getDate(),50,40); g.drawString(當(dāng)前時(shí)間: +t.getTime(),50,80); Time是一個(gè)自定義類(lèi),它可以返回系統(tǒng)當(dāng)前日期和時(shí)間。主類(lèi)ShowTime僅僅聲明了一個(gè)Time對(duì)象,然后調(diào)用對(duì)象的方法取得日期和時(shí)間并輸出到窗口的指定位置。成員變量聲明時(shí)要注意順序,一個(gè)重要的原則是: 使用變量之前必須先聲明它。在getTime方法中特意聲明了一

39、個(gè)字符串變量s,用來(lái)說(shuō)明局部變量和成員變量的區(qū)別。在程序中有多個(gè)類(lèi)時(shí)要使用主類(lèi)的名字作為源程序的名字。 以上幾個(gè)例子的成員變量聲明都是比較簡(jiǎn)單的,只出現(xiàn)了一個(gè)訪問(wèn)控制修飾符private,起到隱藏?cái)?shù)據(jù)的作用,達(dá)到封裝的目的。但有時(shí)需要公開(kāi)一些變量和方法,就可以使用其他修飾符來(lái)完成。實(shí)際上,成員變量的聲明可以是非常復(fù)雜的。成員變量的聲明語(yǔ)句有如下格式: public private protected package / 訪問(wèn)控制修飾符static final transient volatile 4.3.2 成員變量的修飾 1. 訪問(wèn)控制權(quán)限表4.1給出了訪問(wèn)控制修飾符的作用范圍。表4.1 修

40、飾符的作用范圍 修飾符類(lèi)子類(lèi)包所有類(lèi)和包publicprivateprotectedpackage1) public(公共)變量由public修飾的變量稱(chēng)為公共變量,可被任何包中的任何類(lèi)訪問(wèn),只有在確認(rèn)任何外部訪問(wèn)都不會(huì)帶來(lái)不良后果的情況下才將成員聲明為公共的。公共變量對(duì)任何類(lèi)都是可見(jiàn)的,因此它沒(méi)有秘密可言,不具有數(shù)據(jù)保護(hù)功能。例如下面這兩段程序:package P1;public class ClassA public int isPublic; public void publicMethod() System.out.println(公共方法); package P2;import P1

41、.*;class ClassB void accessMethod() ClassA a=new classA(); a.isPublic=10; a.publicMethod(); 在ClassB類(lèi)中引用了公共成員變量isPublic。 2) private(私有)變量由private修飾的變量稱(chēng)為私有變量,只能被聲明它的類(lèi)所使用,拒絕任何外部類(lèi)的訪問(wèn)。私有變量是不公開(kāi)的,它們得到了最好的保護(hù),這是對(duì)類(lèi)進(jìn)行封裝時(shí)使用的主要方法。例如: class ClassA private int isPrivate; private void privateMethod() System.out.pri

42、ntln(私有方法); class ClassB void accessMethod() ClassA a=new ClassA(); a.isPrivate=10; / 非法 a.privateMethod(); / 非法 在ClassB類(lèi)中不能引用私有成員變量a.isPrivate。3) protected(受保護(hù))變量由protected修飾的變量稱(chēng)為受保護(hù)變量,可被聲明它的類(lèi)和派生的子類(lèi)以及同一個(gè)包中的類(lèi)訪問(wèn)。4) package(包)變量由package修飾的變量稱(chēng)為包變量,在聲明時(shí)常常省略package關(guān)鍵字,即沒(méi)有修飾符的成員被視為包成員。包成員可被聲明它的類(lèi)和同一個(gè)包中的其他類(lèi)

43、(包括派生子類(lèi))所訪問(wèn),在其他包中的子類(lèi)則不能訪問(wèn)父類(lèi)的包成員。2. static(靜態(tài))變量static聲明的成員變量被視為類(lèi)的成員變量,而不把它當(dāng)作實(shí)例對(duì)象的成員變量。換句話(huà)說(shuō),靜態(tài)變量是類(lèi)固有的,可以直接引用,其他成員變量?jī)H僅被聲明,只有等到生成實(shí)例對(duì)象后才存在,才可以被引用。基于這樣的事實(shí),也把靜態(tài)變量稱(chēng)為類(lèi)變量,非靜態(tài)變量稱(chēng)為實(shí)例變量。相應(yīng)地,靜態(tài)方法稱(chēng)為類(lèi)方法,非靜態(tài)方法稱(chēng)為實(shí)例方法。 例4.5 靜態(tài)變量的使用示例。class StaticDemo static int x; int y; static public int getX() return x; static publ

44、ic void setX(int newX) x = newX; public int getY() return y; public void setY(int newY) y = newY; public class ShowDemo public static void main(String args) System.out.println(靜態(tài)變量x=+StaticDemo.getX(); System.out.println(實(shí)例變量y=+StaticDemo.getY(); / 非法,編譯時(shí)將出錯(cuò) StaticDemo a= new StaticDemo(); StaticDem

45、o b= new StaticDemo(); a.setX(1); a.setY(2); b.setX(3); b.setY(4); System.out.println(靜態(tài)變量a.x=+a.getX(); System.out.println(實(shí)例變量a.y=+a.getY(); System.out.println(靜態(tài)變量b.x=+b.getX(); System.out.println(實(shí)例變量b.y=+b.getY(); 對(duì)上面的源程序進(jìn)行編譯會(huì)出現(xiàn)如圖4.4所示結(jié)果,不能運(yùn)行該程序。圖 4.4將源程序中的出錯(cuò)語(yǔ)句刪除或使用解釋符/隱藏起來(lái)如: /System.out.printl

46、n(實(shí)例變量y=+StaticDemo.getY(); / 非法,編譯時(shí)將出錯(cuò)再進(jìn)行編譯,即可執(zhí)行該程序,結(jié)果如圖4.5所示。圖 4.5從輸出結(jié)果中可以得出以下幾點(diǎn)結(jié)論: 類(lèi)的靜態(tài)變量可以直接引用,而非靜態(tài)變量則不行。類(lèi)的靜態(tài)變量相當(dāng)于某些程序語(yǔ)言的全局變量。 靜態(tài)方法只能使用靜態(tài)變量,不能使用實(shí)例變量。因?yàn)閷?duì)象實(shí)例化之前,實(shí)例變量不可用。 類(lèi)的靜態(tài)變量只有一個(gè)版本,所有實(shí)例對(duì)象引用的都是同一個(gè)靜態(tài)變量。 對(duì)象實(shí)例化后,每個(gè)實(shí)例變量都被制作了一個(gè)副本,它們之間互不影響。3. final(最終)變量一旦成員變量被聲明為final,在程序運(yùn)行中將不能被改變。這樣的成員變量就是一個(gè)常量。例如: fi

47、nal double PI=3.14159;該語(yǔ)句聲明一個(gè)常量PI,如果在后面試圖重新對(duì)它賦值,將產(chǎn)生編譯錯(cuò)誤。另外,常量名一般用大寫(xiě)字母。常量和直接量一樣不占用內(nèi)存空間。4. transient(過(guò)渡)變量Java語(yǔ)言目前對(duì)transient修飾符沒(méi)有明確說(shuō)明,它一般用在對(duì)象序列化(object serialization)上,說(shuō)明成員變量不許被序列化。5. volatile(易失)變量volatile聲明的成員變量為易失變量,用來(lái)防止編譯器對(duì)該成員進(jìn)行某種優(yōu)化。這是Java語(yǔ)言的高級(jí)特性,僅被少數(shù)程序員使用。 對(duì)象的行為由類(lèi)的方法實(shí)現(xiàn),其他對(duì)象可以調(diào)用一個(gè)對(duì)象的方法,通過(guò)消息的傳遞實(shí)現(xiàn)對(duì)該

48、對(duì)象行為的控制。下面討論如何通過(guò)方法影響對(duì)象的行為。 4.4 成員方法 類(lèi)的設(shè)計(jì)集中體現(xiàn)在成員方法的設(shè)計(jì)上。良好的設(shè)計(jì)可以使類(lèi)更加健壯,功能更加完善。成員方法的設(shè)計(jì)應(yīng)該從類(lèi)的整體行為出發(fā),能正確響應(yīng)外部消息,自然地改變對(duì)象的狀態(tài),并符合相對(duì)獨(dú)立性、結(jié)構(gòu)清晰、可重用性強(qiáng)等編程要求。 4.4.1 成員方法的設(shè)計(jì) 例4.6 方法對(duì)對(duì)象行為的影響,運(yùn)行結(jié)果見(jiàn)圖4.6。圖 4.6import java.awt.*;import java.applet.Applet;class DrawShape private int x, y, shape; public void setPos(int xPos,

49、int yPos) x=xPos; y=yPos; public void setShape(int choice) shape=choice; public void draw(Graphics g) if (shape =1) g.drawRect(x, y, 60, 60); else if (shape =2) g.drawOval(x, y, 60, 60); else g.drawString(形狀參數(shù)不對(duì)!, 20, 120); public class M1 extends Applet final int BOX=1, OVAL=2; DrawShape a=new Draw

50、Shape(); public void paint(Graphics g) a.setPos(40,20); a.setShape(BOX); a.draw(g); a.setPos(200,60); a.setShape(OVAL); a.draw(g); 成員方法相當(dāng)于其他語(yǔ)言的函數(shù)或過(guò)程,是命令語(yǔ)句的集合。成員方法的聲明一般放在成員變量的聲明之后,聲明語(yǔ)句的格式和順序如下: public private protected package / 訪問(wèn)控制修飾符static final abstract native synchronized返回值類(lèi)型 方法名(參數(shù)表)throws 異常類(lèi)

51、型4.4.2 成員方法的聲明與修飾 4種訪問(wèn)控制修飾符和成員變量的修飾符有相同作用,static修飾符亦如此。使用static修飾符的方法稱(chēng)為靜態(tài)方法或類(lèi)方法,非靜態(tài)方法稱(chēng)為實(shí)例方法。靜態(tài)方法體中只能訪問(wèn)靜態(tài)變量,靜態(tài)方法可以通過(guò)對(duì)象來(lái)調(diào)用,也可以通過(guò)類(lèi)名來(lái)調(diào)用。實(shí)例方法體中既可以訪問(wèn)類(lèi)變量,也可以訪問(wèn)實(shí)例變量,但實(shí)例方法只能通過(guò)對(duì)象來(lái)調(diào)用。這些和靜態(tài)變量與實(shí)例變量類(lèi)似。下面主要介紹有不同含義的修飾符。1. final(最終)方法方法被聲明為最終方法后,將不能被子類(lèi)覆蓋,即最終方法能被子類(lèi)繼承和使用但不能在子類(lèi)中修改或重新定義它。這種修飾可以保護(hù)一些重要的方法不被修改,尤其是那些對(duì)類(lèi)的狀態(tài)和行

52、為有關(guān)鍵性作用的方法被保護(hù)以后,可以避免未知情況的發(fā)生。在面向?qū)ο缶幊讨?,子?lèi)可以把父類(lèi)的方法重新定義,使之具有新功能但又和父類(lèi)的方法同名、同參數(shù)、同返回值,這種情況稱(chēng)為方法覆蓋(override)。有時(shí)不便于把整個(gè)類(lèi)聲明為最終類(lèi),這種保護(hù)太嚴(yán)格,不利于編程,此時(shí)可以有選擇地把一些方法聲明為最終方法,同樣可以起到保護(hù)作用。 2. abstract(抽象)方法一個(gè)抽象類(lèi)可以含有抽象方法。所謂抽象方法是指不能實(shí)現(xiàn)的方法,因?yàn)樗鼪](méi)有方法體,所以抽象方法不能出現(xiàn)在非抽象類(lèi)中。一個(gè)抽象類(lèi)可以定義一個(gè)統(tǒng)一的編程接口,使其子類(lèi)表現(xiàn)出共同的狀態(tài)和行為,但各自的細(xì)節(jié)是不同的。子類(lèi)共有的行為由抽象類(lèi)中的抽象方法來(lái)

53、約束,而子類(lèi)行為的具體細(xì)節(jié)則通過(guò)抽象方法的覆蓋來(lái)實(shí)現(xiàn)。這種機(jī)制可增加編程的靈活性。例如,直線、圓和矩形等圖形對(duì)象都有一些共同的狀態(tài)(位置、邊界)和行為(移動(dòng)、改變大小和畫(huà)出)。你可以利用這些共性,把它們聲明為同一個(gè)父類(lèi)的子類(lèi)。但是一個(gè)圓和一個(gè)矩形在很多細(xì)節(jié)方面又是不同的,父類(lèi)不能把這些都包辦代替,這時(shí),一個(gè)抽象父類(lèi)是最佳選擇。首先聲明一個(gè)抽象類(lèi)GraphicObject,提供所有子類(lèi)可共享的成員變量和成員方法,然后聲明一個(gè)抽象的畫(huà)出方法draw。子類(lèi)繼承父類(lèi)后,通過(guò)覆蓋draw實(shí)現(xiàn)畫(huà)出自己的方法??梢赃@樣做: abstract class GraphicObject /抽象父類(lèi) int x,

54、y, width, height; . void moveTo(int newX, int newY) /抽象方法 . void setSize(int sizeW, int sizeH) /抽象方法 . abstract void draw()/抽象方法.GraphicObject的每一個(gè)非抽象子類(lèi)如Circle和Rectangle,都要通過(guò)實(shí)現(xiàn)draw方法來(lái)畫(huà)出自己: class Circle extends GraphicObject void draw() . class Rectangle extends GraphicObject void draw() . 一個(gè)抽象類(lèi)不一定非要包

55、含一個(gè)抽象方法,但一個(gè)類(lèi)如果包含一個(gè)抽象方法就必須聲明為抽象類(lèi)。一個(gè)子類(lèi)如果沒(méi)有實(shí)現(xiàn)父類(lèi)中的抽象方法也必須聲明為抽象類(lèi)。3. native(本地)方法用其他語(yǔ)言編寫(xiě)的方法在Java中稱(chēng)為本地方法。SDK提供了Java本地接口JNI(Java Native Interface),使得Java虛擬機(jī)能運(yùn)行嵌入在Java程序中的其他語(yǔ)言的代碼。這些語(yǔ)言包括C/C+、FORTRAN、匯編語(yǔ)言等。嵌入外部語(yǔ)言代碼出于以下幾點(diǎn)考慮: Java系統(tǒng)包不提供對(duì)平臺(tái)依賴(lài)性程序的支持時(shí);想利用現(xiàn)有的其他語(yǔ)言資源時(shí);出于運(yùn)行速度的要求而使用其他語(yǔ)言開(kāi)發(fā)的運(yùn)行模塊。下面這段程序?qū)崿F(xiàn)了和C語(yǔ)言的接口: class He

56、lloWorld public native void displayHelloWorld(); static System.loadLibrary(hello); public static void main(String args) new HelloWorld().displayHelloWorld(); displayHelloWorld方法被聲明為本地方法,剩下的任務(wù)是用C語(yǔ)言編寫(xiě)程序?qū)崿F(xiàn)這個(gè)方法,并用C語(yǔ)言編譯成動(dòng)態(tài)連接庫(kù)文件hello.DLL。 4. synchronized(同步)方法同步方法用于多線程編程。多線程在運(yùn)行時(shí),可能會(huì)同時(shí)存取一個(gè)數(shù)據(jù)。為避免數(shù)據(jù)的不一致性,應(yīng)將方

57、法聲明為同步方法,對(duì)數(shù)據(jù)進(jìn)行加鎖,以保證線程的安全。詳細(xì)內(nèi)容請(qǐng)參考第8章。5. throws(異常)類(lèi)型程序在運(yùn)行時(shí)可能發(fā)生異?,F(xiàn)象。每一個(gè)異常對(duì)象都對(duì)應(yīng)著一個(gè)異常類(lèi),如果暫時(shí)不希望方法處理某種異常,可將其拋出,使程序得以繼續(xù)運(yùn)行。在前面介紹的例子中就使用過(guò)拋出異常throws IOException(輸入/輸出異常),有關(guān)異常處理的詳細(xì)內(nèi)容請(qǐng)參考第6章。 6. 返回值類(lèi)型Java要求一個(gè)方法必須聲明它的返回值類(lèi)型。如果方法沒(méi)有返回值就用關(guān)鍵字void作為返回值類(lèi)型,否則應(yīng)使用基本數(shù)據(jù)類(lèi)型或?qū)ο箢?lèi)型說(shuō)明返回值類(lèi)型,如下面的語(yǔ)句: public int getX();void setXY(int

58、 x, int y);public String getName();protected Object clone();其中,getX的返回值為int類(lèi)型,setXY沒(méi)有返回值,getName的返回值是String類(lèi),而clone的返回值則為Object類(lèi)。 7. 方法名方法名可以是任何有效的Java標(biāo)識(shí)符。方法名可以和成員變量同名,也可以和成員方法同名。同一個(gè)類(lèi)中的方法同名現(xiàn)象在面向?qū)ο缶幊讨蟹Q(chēng)為方法重載(overload),重載使一個(gè)類(lèi)的多個(gè)方法享有同一個(gè)名稱(chēng),可以減輕程序員的負(fù)擔(dān)。例如: class DataPrint void print(String s) . void print(

59、int i) . void print(float f) . 在非面向?qū)ο缶幊陶Z(yǔ)言中,需要定義3個(gè)不同名稱(chēng)的函數(shù)printString、printInt、printFloat才能實(shí)現(xiàn)3種類(lèi)型的數(shù)據(jù)輸出。在Java中,只要記住一個(gè)方法名就行了,無(wú)論向print方法傳遞哪一種參數(shù),都能得到正確的輸出。同名方法由參數(shù)個(gè)數(shù)和類(lèi)型來(lái)區(qū)分,同一個(gè)類(lèi)中不能有名稱(chēng)、參數(shù)個(gè)數(shù)和參數(shù)類(lèi)型都相同的方法出現(xiàn)。 8. 參數(shù)表方法的調(diào)用者正是通過(guò)參數(shù)表將外部消息傳遞給方法的。在參數(shù)表中要聲明參數(shù)的類(lèi)型,并用逗號(hào)分隔多個(gè)參數(shù)。 方法體包含在一對(duì)大括號(hào)中,即使方法體中沒(méi)有語(yǔ)句,一對(duì)大括號(hào)也是必不可少的。使用各種語(yǔ)句結(jié)構(gòu)組成方

60、法主體,實(shí)現(xiàn)程序的功能,是設(shè)計(jì)方法體的目的。下面這段程序是一個(gè)處理格式化字符串的方法: 4.4.3 方法體 public String toString(int arr) int i, n=arr.size(); StringBuffer s=new StringBuffer(); s.append(); for (i=0; in; i+) s.append (Integer.toString(arri); if (in-1) s.append(,); s.append(); return s.toString();方法體toString中的參數(shù)是一個(gè)整型數(shù)組arr,該方法的任務(wù)是將數(shù)組元素轉(zhuǎn)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論