Java程序設計類包和接口_第1頁
Java程序設計類包和接口_第2頁
Java程序設計類包和接口_第3頁
Java程序設計類包和接口_第4頁
Java程序設計類包和接口_第5頁
已閱讀5頁,還剩54頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

本章介紹Java中面向對象的程序設計的基本方法,包括類的定義、類的繼承、包、訪問控制、修飾符、接口等方面的內容。

4.1類、域、方法類類是組成Java程序的基本要素。它封裝了一類對象的狀態(tài)和方法,是這一類對象的原型。在前幾章的例子中,我們已經定義了一些簡單的類,如HelloworldApp類。4.1.1域field和方法methodclassPerson{ Stringname; intage; voidsayHello(){ System.out.println("Hello!Mynameis"+name); }}域對應類的靜態(tài)屬性。域又稱為域變量、屬性、成員變量等方法是類的動態(tài)屬性,標志了類所具有的功能和操作,Java的方法與其他語言中的函數(shù)或過程類似4.1.2構造方法構造方法是一種特殊的方法。Java中的每個類都有構造方法,用來初始化該類的一個新的對象。構造方法具有和類名相同的名稱,而且不返回任何數(shù)據(jù)類型。 Person(Stringn,inta){ name=n; age=a; }默認構造方法一般情況下,類都有一個至多個構造方法,如果在定義類對象時沒有定義任何構造方法,系統(tǒng)會自動產生一個構造方法,稱為默認構造方法(defaultconstructor)。默認構造方法不帶參數(shù),并且方法體為空。4.1.3

使用對象要訪問或調用一個對象的域或方法,需要用算符“.”連接對象及其域或方法。如:System.out.println();

p.sayHello();由于只能通過對象變量來訪問這個對象的域或方法,不通過引用變量就無法訪問其中的域或方法。對于訪問者而言,這個對象是封裝成一個整體的,這正體現(xiàn)了面向對象的程序設計的“封裝性”。4.1.4方法重載(overload)通過方法重載可以實現(xiàn)多態(tài)。方法重載即指多個方法可以享有相同的名字。但是這些方法的參數(shù)必須不同,或者是參數(shù)個數(shù)不同,或者是參數(shù)類型不同,下例中我們通過方法重寫分別接收一個或幾個不同數(shù)據(jù)類型的數(shù)據(jù)。MethodOverloadingTest.java編譯器根據(jù)參數(shù)的個數(shù)和類型來決定當前所使用的方法。如果兩個方法的聲明中,參數(shù)的類型和個數(shù)均相同,只是返回類型不同,則編譯時會產生錯誤,即返回類型不能用來區(qū)分重寫的方法。而且重寫的多個方法必須返回相同的數(shù)據(jù)類型。運行結果為:C:\>javaMethodOverloadingTestReceiveoneintdatai=1Receivetwointdatasx=2y=3Receiveonedoubledatad=12.56Receiveastrings=veryinteresting,isn'tit?4.1.5this的使用

1.在方法及構造方法中,使用this來訪問域及方法例如,方法sayHello中使用name和使用是相同的。即:voidsayHello(){ System.out.println("Hello!Mynameis"+name); } 與

voidsayHello(){ System.out.println("Hello!Mynameis"+); }的含義是相同的。2.使用this解決局部變量與域同名的問題 使用this還可以解決局部變量(方法中的變量)或參數(shù)變量與域變量同名的問題。如,在構造方法中,經常這樣用:

Person(intage,Stringname) { this.age=age; =name; }這里,this.age表示域變量,而age表示的是參數(shù)變量。3.構造方法中,用this調用另一構造方法 構造方法中,還可以用this來調用另一構造方法。如:

Person() { this(0,""); }

如果,在構造方法中調用另一構造方法,則這條調用語句必須放在第一句。(關于構造方法的更復雜的問題,將在第5章中進一步講述。)4.2類的繼承繼承(inheritance)是面向對象的程序設計中最為重要的特征之一。由繼承而得到的類為子類(subclass),被繼承的類為父類或超類(superclass),父類包括所有直接或間接被繼承的類。一個類只能有一個直接父類。子類繼承父類的狀態(tài)和行為,同時也可以修改父類的狀態(tài)或重載父類的行為,并添加新的狀態(tài)和行為。采用繼承的機制來組織、設計系統(tǒng)中的類,可以提高程序的抽象程度,使之更接近于人類的思維方式,同時也通過繼承能較好地實現(xiàn)代碼重用,可以提高程序開發(fā)效率,降低維護的工作量。4.2.1派生子類Java中的繼承是通過extends關鍵字來實現(xiàn)的classSubClassextendsSuperClass{……}如果沒有extends子句,則該類默認為java.lang.Object的子類。所以,Java中,所有的類都是通過直接或間接地繼承java.lang.Object得到的。繼承關系在UML圖中,是用一個箭頭來表示子類與父類的關系的。相當于isa類Student從類Person繼承,定義如下:

classStudentextendsPerson{ //… }4.2.2

域的繼承與隱藏、添加1.域的繼承子類可以繼承父類的所有域Student自動具有Person的屬性(name,age)2.域的隱藏子類重新定義一個與從父類那里繼承來的域變量完全相同的變量,稱為域的隱藏。域的隱藏在實際編程中用得較少。3.域的添加 在定義子類時,加上新的域變量,就可以使子類比父類多一些屬性。如:

classStudentextendsPerson{ Stringschool; intscore;}4.2.3方法的繼承、覆蓋與添加1.方法的繼承父類的非私有方法也可以被子類自動繼承。如,Student自動繼承Person的方法sayHello和isOlderThan。2.方法的覆蓋正像子類可以定義與父類同名的域,實現(xiàn)對父類域變量的隱藏一樣,子類也可以重新定義與父類同名的方法,實現(xiàn)對父類方法的覆蓋(Overriding)。voidsayHello(){ System.out.println("Hello!Mynameis"+name+".Myschoolis"+school); }

可見,通過方法的覆蓋,能夠修改對象的同名方法的具體實現(xiàn)方法。3.方法的重載 一個類中可以有幾個同名的方法,這稱為方法的重載(Overloading)。同時,還可以重載父類的同名方法。與方法覆蓋不同的是,重載不要求參數(shù)類型列表相同。重載的方法實際是新加的方法。 如,在類Student中,重載一個名為sayHello的方法:

voidsayHello(Studentanother){ System.out.println("Hi!"); if(school==another.school)System.out.println("Shoolmates"); }4.方法的添加 子類可以新加一些方法,以針對子類實現(xiàn)相應的功能。 如,在類Student中,加入一個方法,對分數(shù)進行判斷:

booleanisGoodStudent(){ returnscore>=90; }4.2.4super的使用1.使用super訪問父類的域和方法 子類自動地繼承父類的屬性和方法,一般情況下,直接使用父類的屬性和方法,也可能以使用this來指明本對象。注意:正是由于繼承,使用this可以訪問父類的域和方法。但有時為了明確地指明父類的域和方法,就要用關鍵字super。例如:父類Student有一個域age,在子類Student中用age,this.age,super.age來訪問age是完全一樣的:

voidtestThisSuper(){ inta; a=age; a=this.age; a=super.age; }

當然,使用super不能訪問在子類中添加的域和方法。有時需要使用super以區(qū)別同名的域與方法。如,使用super可以訪問被子類所隱藏了的同名變量。又如,當覆蓋父類的同名方法的同時,又要調用父類的方法,就必須使用super。如:

voidsayHello(){ super.sayHello(); System.out.println("Myschoolis"+school); }從這里可以看出,即使同名,也仍然可以使用父類的域和方法,這也使得在覆蓋父類的方法的同時,又利用已定義好的父類的方法。2.使用父類的構造方法在嚴格意義上,構造方法是不能繼承的。比如,父類Person有一個構造方法Person(String,int),不能說子類Student也自動有一個構造方法Student(String,int)。但是,這不并意味著子類不能調用父類的構造方法。子類在構造方法中,可以用super來調用父類的構造方法。

Student(Stringname,intage,Stringschool){ super(name,age); this.school=school; }使用時,super()必須放在第一句。有關構造方法的更詳細的討論,參見第5章。4.2.5父類對象與子類對象的轉換類似于基本數(shù)據(jù)類型數(shù)據(jù)之間的強制類型轉換,存在繼承關系的父類對象和子類對象之間也可以在一定條件下相互轉換。父類對象和子類對象的轉化需要遵循如下原則。(1)子類對象可以被視為其父類的一個對象,如一個Student對象也是一個Person對象。(2)父類對象不能被當做其某一個子類的對象。(3)如果一個方法的形式參數(shù)定義的是父類對象,那么調用這個方法時,可以使用子類對象作為實際參數(shù)。(4)如果父類對象引用指向的實際是一個子類對象,那么這個父類對象的引用可以用強制類型轉換成子類對象的引用。例:Student.java4.3包Java提供包(package)來管理類名空間。包實際上提供了一種命名機制和可見性限制機制。包是一種松散的類的集合,一般不要求處于同一個包中的類有明確的相互關系,如包含、繼承等,但是由于同一包中的類在默認情況下可以互相訪問,所以為了方便編程和管理,通常把需要在一起工作的類放在—個包里。4.3.1package語句packagepkg1[.pkg2[.pkg3…]];包及子包的定義,實際上是為了解決名字空間、名字沖突,它與類的繼承沒有關系。事實上,一個子類與其父類可以位于不同的包中。Java的JDK提供的包包括:java.applet,java.awt,java.awt.image,java.awt.peer,java.io,java.lang,,java.util,javax.swing,等。包層次的根目錄是由環(huán)境變量CLASSPATH來確定的。 在簡單情況下,Java源文件默認為package語句,這時稱為無名包(unamedpackage)。無名包不能有子包。4.3.2import語句為了能使用Java中已提供的類,需要用import語句來引入所需要的類。import語句的格式為:importpackage1[.package2…].(classname|*);其中,package1[.package2…]表明包的層次,與package語句相同,它對應于文件目錄,classname則指明所要引入的類,如果要從一個包中引入多個類,則可以用星號(*)來代替。例如:importjava.awt.*;importjava.util.Date;Java編譯器為所有程序自動引入包java.lang,因此不必用import語句引入它包含的所有的類,但是若需要使用其他包中的類,必須用import語句引入。注意:使用星號(*)只能表示本層次的所有類,不包括子層次下的類。例如,經常需要用兩條import語句來引入兩個層次的類:

importjava.awt.*; importjava.awt.event.*;4.3.3編譯和運行包中的類使用javac可以將.class文件放入到相應的目錄,只需要使用一個命令選項-d來指明包的根目錄即可。javac-dd:\tang\ch04d:\tang\ch04\pk\TestPkg.javajavac-d.pk\*.java其中,“.”表示當前目錄運行該程序,需要指明含有main的類名:

javapk.TestPkg4.3.4CLASSPATH

在編譯和運行程序中,經常要用到多個包,怎樣指明這些包的根目錄呢?簡單地說,包層次的根目錄是由環(huán)境變量CLASSPATH來確定的。具體操作有兩種方法。 一是在java及javac命令行中,用-classpath選項來指明,如:

java–classpathd:\tang\ch04;c:\java\classes;.pk.TestPkg

二是設定classpath環(huán)境變量,用命令行設定環(huán)境變量,如:

Setclasspath=d:\tang\ch04;c:\java\classes;.在Windows中還可以按第2章中的辦法設定環(huán)境變量。4.4訪問控制符4.4.1

成員的訪問控制符同一個類中同一個包中不同包中的子類不同包中的非子類privateYes默認YesYesprotectedYesYesYespublicYesYesYesYes4.4.2

類的訪問控制符在定義類時,也可以用訪問控制符。類的訪問控制符或者為public,或者默認。若使用public,其格式為: publicclass類名{

…… }

如果類用public修飾,則該類可以被其他類所訪問;若類默認訪問控制符,則該類只能被同包中的類訪問。4.4.3setter與getter

在Java編程中,有一種常見的做法,是將所有的或部分的域用private修飾,從而更好地將信息進行封裝和隱藏。在這樣的類中,用setXXXX和getXXXX方法對類的屬性進行存取,分別稱為setter與getter。這種方法有以下優(yōu)點。(1)屬性用private更好地封裝和隱藏,外部類不能隨意存取和修改。(2)提供方法來存取對象的屬性,在方法中可以對給定的參數(shù)的合法性進行檢驗。(3)方法可以用來給出計算后的值。(4)方法可以完成其他必要的工作(如清理資源、設定狀態(tài),等等)。(5)只提供getXXXX方法,而不提供setXXXX方法,可以保證屬性是只讀的。例如:在類Person中將域age以set和get方法提供。classPerson2{ privateintage; publicvoidsetAge(intage){ if(age>0&&age<200)this.age=age; } publicintgetAge(){ returnage; }}4.5非訪問控制符非訪問控制符基本含義修飾類修飾成員修飾局部變量static靜態(tài)的、非實例的、類的只可以修飾內部類Yesfinal最終的、不可改變的YesYesYesabstract抽象的、不可實例化的YesYes4.5.1static靜態(tài)域最本質的特點是:它們是類的域,不屬于任何一個類的具體對象實例。它不保存在某個對象實例的內存區(qū)間中,而是保存在類的內存區(qū)域的公共存儲單元。換句話說,對于該類的任何一個具體對象而言,靜態(tài)域是一個公共的存儲單元,任何一個類的對象訪問它,取到的都是相同的數(shù)值;同樣任何一個類的對象去修改它,也都是在對同一個內存單元進行操作。類變量可以通過類名直接訪問,也可以通過實例對象來訪問,兩種方法的結果是相同的。如我們用到的JDK中的System類的in和out對象,就是屬于類的域,直接用類名來訪問,即System.in和System.out。又如,在類Person中可以定義一個類域為totalNum:classPerson{ staticlongtotalNum; intage; StringName;}totalNum代表人類的總人數(shù),它與具體對象實例無關??梢杂袃煞N方法來訪問:Person.totalNum和p.totalNum(假定p是Person對象)。2.static方法用static修飾符修飾的方法僅屬于類的靜態(tài)方法,又稱為類方法。與此相對,不用static修飾的方法,則為實例方法。類方法的本質是該方法是屬于整個類的,不是屬于某個實例的。聲明一個方法為static有以下幾重含義。(1)非static的方法是屬于某個對象的方法,在這個對象創(chuàng)建時,對象的方法在內存中擁有自己專用的代碼段。而static的方法是屬于整個類的,它在內存中的代碼段將隨著類的定義而進行分配和裝載,不被任何一個對象專有。(2)由于static方法是屬于整個類的,所以它不能操縱和處理屬于某個對象的成員變量,而只能處理屬于整個類的成員變量,即static方法只能處理static域或調用static方法。(3)類方法中,不能訪問實例變量。在類方法中不能使用this或super。(4)調用這個方法時,應該使用類名直接調用,也可以用某一個具體的對象名。 例如:前面章節(jié)用到的方法Math.random(),Integer.parseInt()等就是類方法,直接用類名進行訪問。4.5.2final1.final類如果一個類被final修飾符所修飾和限定,說明這個類不能被繼承,即不可能有子類。2.final方法final修飾符所修飾的方法,是不能被子類所覆蓋的方法。3.final域及final局部變量final域、final局部變量,它們的值一旦給定,就不能更改。大體上說,final域、final局部變量是只讀量,它們能且只能被賦值一次,而不能被賦值多次。一個域被staticfinal兩個修飾符所限定時,它實際的含義就是常量,如Integer.MAX_VALUE(表示最大整數(shù))、Math.PI(表示圓周率)就是這種常量。在程序中,通常用static與final一起使用來指定一個常量。在定義staticfinal域時,若不給定初始值,則按默認值進行初始化(數(shù)值為0,boolean型為false,引用型為null)。在定義final域時,若不是static的域,則必須且只能賦值一次,不能缺省。這種域的賦值的方式有兩種:一是在定義變量時賦初始值,二是在每一個構造函數(shù)中進行賦值。在定義final局部變量(方法中的變量)時,也必須且只能賦值一次。它的值可能不是常量,但它的取值在變量存在期間不會改變。4.5.3abstract1.abstract類凡是用abstract修飾符修飾的類被稱為抽象類。抽象類不能被實例化2.abstract方法被abstract所修飾的方法叫抽象方法,抽象方法的作用在為所有子類定義一個統(tǒng)一的接口。對抽象方法只需聲明,而不需實現(xiàn),即用分號(;)而不是用{},格式如下:abstractreturnTypeabstractMethod([paramlist]);抽象類中可以包含抽象方法,也可以不包含abstract方法。但是,一旦某個類中包含了abstract方法,則這個類必須聲明為abstract類。抽象方法在子類中必須被實現(xiàn),否則子類仍然是abstract的。4.6接口Java通過接口使得處于不同層次,甚至互不相關的類可以具有相同的行為。接口就是方法定義和常量值的集合。它的用處主要體現(xiàn)在下面幾個方面:1.通過接口可以實現(xiàn)不相關類的相同行為,而不需要考慮這些類之間的層次關系。2.通過接口可以指明多個類需要實現(xiàn)的方法。3.通過接口可以了解對象的交互界面,而不需了解對象所對應的類。在接口中定義這些類共同的行為,然后由每個類分別實現(xiàn)這些行為。與C++不同,Java不支持多重繼承,而是用接口實現(xiàn)比多重繼承更強的功能。多重繼承指一個類可以為多個類的子類,它使得類的層次關系不清楚,而且當多個父類同時擁有相同的成員變量和方法時,子類的行為是不容易確定的,這給編程帶來了困難。單一繼承則清楚地表明了類的層次關系,指明子類和父類各自的行為。接口則把方法的定義和類的層次區(qū)分開來,通過它可以在運行時動態(tài)地定位所調用的方法。同時接口中可以實現(xiàn)“多重繼承”,且一個類可以實現(xiàn)多個接口。正是這些機制使得接口提供了比多重繼承更簡單、更靈活、而且更強勁的功能。1.接口的定義接口的定義包括接口聲明和接口體兩部分。如下:interfaceDeclaration{interfaceBody}

(1)接口聲明:

最簡單的接口聲明如下:interfaceinterfaceName{……}通常接口以able或ible結尾,表明接口能完成一定的行為。接口聲明中還可以包括對接口的訪問權限以及它的父接口列表。完整的接口聲明如下:[public]interfaceinterfaceName[extendslistOfSuperInterface]{……}其中public指明任意類均可以使用這個接口,缺省情況下,只有與該接口定義在同一個包中的類才可以訪問這個接口。extends子句與類聲明中的extends子句基本相同,不同的是一個接口可以有多個父接口,用逗號隔開,而一個類只能有一個父類。子接口繼承父接口中所有的常量和方法。(2)接口體接口體中包含常量定義和方法定義兩部分。常量定義的格式為:typeNAME=value;其中type可以是任意類型,NAME是常量名,通常用大寫,value是常量值。在接口中定義的常量可以被實現(xiàn)該接口的多個類共享,它與C中用#define以及C++中用const定義的常量是相同的。在接口中定義的常量具有public,final,static的屬性。方法定義的格式為:returnTypemethodName([paramlist]);接口中只進行方法的聲明,而不提供方法的實現(xiàn),所以,方法定義沒有方法體,且用分號(;)結尾。在接口中聲明的方法具有public和abstract屬性。另外,如果在子接口中定義了和父接口同名的常量或相同的方法,則父接口中的常量被隱藏,方法被重載。下面我們給出一個接口的定義:interfaceCollection{intMAX_NUM=100;voidadd(Objectobj);voiddelete(Objectobj);Objectfind(Objectobj);intcurrentCount();}2.接口的實現(xiàn)在類的聲明中用implements子句來表示一個類使用某個接口,在類體中可以使用接口中定義的常量,而且必須實現(xiàn)接口中定義的所有方法。一個類可以實現(xiàn)多個接口。下面我們在類FIFOQueue中實現(xiàn)上面所定義的接口collection:classFIFOQueueimplementscollection{publicvoidadd(Objectobj){……}publicvoiddelete(Objectobj){……}publicObjectfind(Objectobj){……}publicintcurrentCount{……}在類中實現(xiàn)接口所定義的方法時,方法的聲明必須與接口中所定義的完全一致。3.接口類型接口可以作為一種引用類型來使用。任何實現(xiàn)該接口的類的實例都可以存儲在該接口類型的變量中,通過這些變量可以訪問類所實現(xiàn)的接口中的方法。Java運行時系統(tǒng)動態(tài)地確定該使用哪個類中的方法。把接口作為一種數(shù)據(jù)類型可以不需要了解對象所對應的具體的類,以前面所定義的接口Collection和實現(xiàn)該接口的類FIFOQueue為例,下例中,我們以Collection作為引用類型來使用。classInterfaceType{publicstaticvoid

溫馨提示

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

評論

0/150

提交評論