




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
JAVA語言程序設計3.1面向對象編程概述3.2類的定義3.3對象3.4源文件的布局與類的封裝3.5方法的調用3.6類的繼承3.7類的高級特性本章小結第三章目錄教學目標:Java是完全面向對象的語言。類和對象是面向對象語言中非常重要的概念。本章將主要介紹面向對象的基本概念和面向對象的程序設計方法,Java語言中類的抽象和定義,對象的創建和使用,類的繼承,方法的重載、覆蓋、多態以及類的高級特性。在理解概念、編寫和調試程序中遇到的各種問題,需要用不怕吃苦的奮斗精神和團結協作的合作精神來解決,填充程序漏洞,編寫出可持續復用的程序。教學重點:掌握Java編程語言中類的抽象與定義。理解、掌握Java編程語言中對象的概念與創建,以及類與對象之間的關系。理解、掌握構造方法的概念、定義與作用。理解、掌握類的繼承關系的定義和使用。掌握類的多態。了解類的高級特性第二章面向對象編程(ObjectOrientedProgramming,OOP)是一種計算機編程架構,它的作用是讓程序員從人類思考的角度,而不是以計算機思考的角度來處理問題。它大大地降低了軟件開發的難度,使編程就像搭積木一樣簡單,是當今計算機編程中一股勢不可擋的潮流。面向對象編程已成為現代軟件開發的必然選擇。通過掌握面向對象的技術,程序員能開發出復雜、高級的系統,這些系統是完整健全的,但又是可擴充的。面向對象編程是建立在把對象作為基本實體看待的面向對象的模型上的,這種模型可以使對象之間產生交互。3.1面向對象編程概述面向對象技術利用對現實世界中對象的抽象和對象之間相互關聯和相互作用的描述來對現實世界進行模擬,并且使其映射到目標系統中。面向對象的特點主要概括為抽象性、繼承性、封裝性和多態性。抽象性是指對現實世界中某一類實體或事件進行抽象,從中提取共同信息,找出共同規律,反過來又把它們集中在一個集合中,定義為所設計目標系統中的對象。繼承性是新的對象類由繼承原有對象類的某些特性或全部特性而產生出來,原有對象類稱為基類(或超類、父類),新的對象類稱為派生類(或子類),子類可以直接繼承父類的共性,又可以發展自己的個性。繼承性簡化了對新的對象類的設計。3.1面向對象編程概述封裝性是指對象的使用者通過預先定義的接口關聯到某一對象的行為和屬性時,無須知道這些行為是如何實現的,即用戶使用對象時無須知道對象內部的運行細節。這樣,以前所開發的系統中已使用的對象能夠在新系統中重新采用,減少了新系統中分析、設計和編程的工作量。多態性是指不同類型的對象可以對相同的行為做出不同的反應。多態性豐富了對象的內容,擴大了對象的適應性,改變了對象單一繼承的關系。3.1面向對象編程概述在面向對象的程序設計中,類是程序的基本單元。類是描述對象的“基本原型”,它定義一類對象所能擁有的數據和能完成的操作。相似的對象可以歸并到同一個類中去,就像傳統語言中的變量與數據類型的關系一樣。類中不但有變量,還有與之相關的操作所定義的方法。進行Java程序設計,實際上就是定義類的過程。一個Java源程序文件往往是由許多個類組成的。從用戶的角度看,Java源程序中的類分為兩種,一種是系統定義的類,即Java類庫,例如父類Object,所有Java的類都派生自Object類;另一種是用戶自己定義的類。3.2類的定義類就像一個軟件藍圖,可以用于實例化許多的單個對象。類定義對象的數據元素(屬性)的集合和行為或功能(或稱方法,用于操作對象或執行相關對象間的交互)的集合。屬性和方法一起稱為成員。類是描述了具有相同屬性和行為的一組對象,它抽象出一組對象所具有的共同特征。例如我們常說的人類、學生、教師、工人、魚、汽車、動物等等,都可以是我們根據它們相同的特征抽象出來的類。Java中的類可以包括變量和方法兩大部分。類的成員變量可以是基本數據類型,也可以是引用數據類型;類的方法用于處理該類的數據。3.2類的定義類定義的一般格式:(1)類的修飾符public:表示公有的,允許其他類(沒有限制)訪問本類,一個源文件僅可以有一個public修飾的類,并且該類的名稱與Java的源文件同名。default(默認):此修飾符可缺省不寫,default修飾的類可被當前包中的其他類訪問。通常情況下,類的訪問權限只有兩種:public和default。只有內部類可以有protected和private的訪問權限。3.2類的定義(2)類名稱在關鍵字class后邊需要聲明用戶定義類的名稱。每個類都擁有自己的名字空間,需要使用一個標識符來表示。類名不能是Java中的關鍵字,必須符合Java中標識符的命名規則,可以是以字母、_或者$開頭。標識符最好“見名知義”,而且規范大小寫的使用方式,類名和接口名一般由一個或者幾個單詞組成,每個單詞的首字母大寫,如Object類,StringBuffer類,Frame類等。3.2類的定義(3)類體在類的定義中,花括號內的部分為類體。一般情況下,類體的內容主要包括兩大部分,分別為變量定義及初始化和方法定義及方法體。3.2類的定義(3)類體①類的定義中成員變量的聲明格式:類的定義中成員變量的聲明格式:變量修飾符可以是public、protected、default、private,修飾符用來表示變量的訪問控制,即訪問權限。public代表公有的,其所修飾的類可以被所有其他的類引用;default表示默認(缺省)的,其所修飾的類可以被本包中的其他類引用;protected表示保護的,其所修飾的類可以被該類自身、子類、同一包中的其他類引用;private表示私有的,其所修飾的類僅可被該類內部引用和修改,不能被其他任何類(包括子類)引用。3.2類的定義變量的數據類型可以是Java中任意的數據類型,包括基本數據類型和引用數據類型。在一個類體中的成員變量的名稱應該符合標識符的命名規則并且是唯一的。在定義成員變量的過程中,可以對成員變量直接進行賦初值,也就是成員變量的初始化。如果一個成員變量沒有被賦初值,那么這個成員變量在使用的時候,將取該種數據類型的默認值。Java中成員變量的默認初值都是確定的,布爾變量的初值為false;整型變量的初值為0;浮點型變量的初值為0.0;引用(復雜)數據類型變量的初值為null。例如:3.2類的定義②構造方法是一個類體中比較特殊的部分,它可以省略。也就是說,一個類可以沒有構造方法。3.2類的定義③成員方法是完成特定功能的、相對獨立的程序段。它具有可以在不同的程序中被多次調用、增強程序結構的清晰度、提高編程效率的功能。它的基本組成包括方法頭和方法體。方法聲明基本格式如下:方法的修飾符包括public、private、protected、default(缺省),它的訪問權限與成員變量修飾符的訪問權限的說明相同。3.2類的定義方法的返回值類型是方法執行完后返回值的數據類型,它可以是我們學過的任意一種合法的數據類型。若方法沒有返回值,則用void關鍵字說明。若方法有返回值,則方法體中至少有一條return語句,形式為“return(表達式);”,其中表達式的值即方法的返回值,方法的返回值必須與方法頭聲明的返回值類型相匹配。return語句的作用是退出當前方法,使控制流程返回到調用該方法的語句之后的下一個語句。方法名采用用戶定義的標識符,不要與Java關鍵字重名。根據Java編程語言的編碼約定,方法名除第一個單詞的首字母小寫外,其余單詞的首字母都是大寫,與類名的取名類似。3.2類的定義參數列表指調用方法時,應該傳遞的參數個數及其對應的數據類型。在Java中,一個方法可以有0個或者多個參數,當方法中有多個參數時,每個參數之間用逗號分隔開。參數在定義時要確定參數的數據類型和參數名。方法在聲明時的參數被稱為形式參數(簡稱形參),當用戶調用方法時,應該給對應的參數一個實際的值,稱為實際參數(簡稱實參)。花括號內的部分是方法體。方法體一般包含變量的聲明和語句。在方法體中聲明的變量,我們稱為局部變量,它的使用范圍只在方法體內有效。方法的聲明不能嵌套,即不能在方法體中再聲明其它的方法。3.2類的定義【例3-1】抽象出圓這個類,類中有半徑這個屬性,求圓的面積和圓的周長的方法。在例3-1中,常量PI、變量r是類的成員變量,方法getArea()和getCircum()是類的成員方法。3.2類的定義publicclassExample3_1{publicfinalfloatPI=3.14f;//定義常量PIprivatedoubler=2;//定義圓的半徑publicdoublegetArea(){//求圓的面積方法doublearea=PI*r*r;returnarea;}publicvoidgetCircum(){//求圓的周長方法 doublec=2*PI*r;System.out.println("圓的周長為"+c);}}④main()方法是主方法,也稱主函數,是Java程序中比較特殊的方法。在Java中規定,main()方法是Java應用程序執行的入口函數,也是出口函數。Java應用程序想要運行必須含有main()方法。若沒有main()方法,則該類不能直接運行。主方法的寫法如下:在主方法的頭部的定義中只有參數args的名稱是可以修改的,其余部分為固定寫法。主方法可以放在任意一個類體中。程序在運行時,一定是執行帶有主方法的類,并且直接調用主方法。方法體內可以是我們所使用的任何合法的語句塊。3.2類的定義【例3-2】根據矩形的特點,抽象出矩形類,定義矩形類的屬性和方法。3.2類的定義classExample3_2{privateintlength=6;//定義長privateintwidth=10;//定義寬publicvoidsetValue(intl,intw){//設置長和寬的值 length=l;width=w;}publicintgetC(){//求周長的方法intc=2*(length+width);returnc;}publicvoidgetS(){//求面積的方法 ints=length*width;System.out.println("矩形的面積為"+s);}publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub Example3_2e1=newExample3_2(); e1.getS(); System.out.println("長度="+e1.getC()); }}類是Java程序的核心。類是對對象的抽象描述,描述了每個對象包含的數據和每個對象表現的行為。對象是類的一個實例,是一個具體的事物。對象所具有的共同的特征或狀態被抽類為類的屬性,即成員變量。對象共同的的操作或者行為被抽象為類的方法。根據類來創建具體的對象,稱為類的實例化。類的實例化創建了對象。類是對象的模版,決定著對象的屬性和方法。3.3對象3.3.1創建對象對象的聲明實例化和初始化3.3對象1.對象的聲明格式為:說明:Example3_1是一個類的名稱,是一個復雜的數據類型。這條語句代表了c1可以是一個Example3_1類對象的引用。3.3對象2.類的實例化和初始化類的實例化指使用運算符new為對象分配內存空間,一個類的不同對象分別占據不同的內存空間。類的實例化格式為:說明:new關鍵字在內存中開辟了一段新的空間,該空間存儲的是對象的屬性。類名([參數列表])的調用是為該對象的每一個成員變量賦初值。對象創建成功之后,使用賦值符號“=”將對象的地址存放在引用變量c1當中。3.3對象創建一個對象的語法也可以將對象的聲明和實例化合并。格式為:說明:Java的對象由類創建,所以應先說明創建對象所屬的類名,再說明創建對象的名稱。“=”是賦值符號,“new類名([參數列表])”使系統為對象創建自己的內存空間并自動調用構造方法初始化成員變量。3.3對象3.3.2使用對象在程序設計中,創建對象的目的是使用對象。創建一個對象就是要為對象的各個成員屬性分配內存空間。使用對象就是通過對象來引用成員變量。對象不但可以引用自己的成員變量,還可以調用成員方法。對象無論是引用成員變量還是成員方法,都通過”.”運算符來實現。3.3對象1.引用成員變量格式為:3.3對象1.引用成員變量一個類可以聲明多個對象,創建對象后,系統會為每個對象分配存儲空間。每個對象單獨擁有自己的數據成員的存儲空間,每個對象數據成員的值可以互不相同,并互不影響。例如:表示分別創建了Circle類的對象c2和c3,每個對象所占用的內存空間并不相同。其中對象c2的成員變量r的值為100,而對象c3的成員變量r的值為200,兩者并不互相影響。3.3對象2.調用成員方法格式為:例如:與各個對象都存儲自己的成員變量不同,各個對象共享類的成員方法,也就是類的成員方法只有一個副本存在。方法只有在被調用的時候才加載。3.3對象【例3-3】引用類的成員變量和成員方法。3.3對象publicclassExample3_3{publicfinalfloatPI=3.14f;//定義常量PIprivatedoubler=2;//定義圓的半徑publicdoublegetR(){ returnr;}publicvoidsetR(doubler){ this.r=r; }publicdoublegetArea(){//求圓的面積方法 doublearea=PI*r*r;//直接調用本類中的成員變量r和PI returnarea;}publicvoidgetCircum(){//求圓的周長方法 doublec=2*PI*r;//直接調用本類中的成員變量r和PI System.out.println("圓的周長為"+c);}}
classTest{ publicstaticvoidmain(Stringargs[]){ Example3_3c2=newExample3_3(); //創建類的對象,并賦值給類的引用c2 Example3_3c3=newExample3_3(); //創建類的對象,并賦值給類的引用c3 //c2.r=10;//調用成員變量。對象c2的成員變量r賦值為10 //c3.r=20;//調用成員變量。對象c3的成員變量r賦值為20 c2.setR(10); c3.setR(20); doublea=c2.getArea();
//通過對象來調用類中的成員方法 doubleb=c3.getArea();
//通過對象來調用類中的成員方法 System.out.println("對象c2的面積為"+a); //輸出對象c2的面積 System.out.println("對象c3的面積為"+b); //輸出對象c3的面積 }
}
3.3.3構造方法構造方法又稱構造器或構造函數,主要作用是實現對象的初始化,為對象的數據成員賦初值。定義構造方法的格式為:3.3對象構造方法與其他普通的成員方法不同,它具有以下幾個特點:(1)構造方法的名稱與類名相同。例如,類Example3_1中的構造方法名稱為Example3_1。(2)構造方法沒有返回值類型。在聲明構造方法的時候,不需要寫返回值,也不用void關鍵字。(3)構造方法可以帶有若干個形參,也可以沒有任何形參。例如,類Example3_1中的構造方法可以聲明為“為Example3_1(){};”也可以聲明為“Example3_1(doubleradius){};”,或者其他參數的形式。(4)構造方法的調用。構造方法不能由編程人員直接調用,而在創建對象時,使用new關鍵字由系統自動調用。3.3對象(5)構造方法的缺省。如果在類中沒有顯式地定義構造方法,則系統自動為類體生成一個默認的構造方法。默認的構造方法在類中不寫出,但是默認為訪問修飾符與類相同,名稱與類名相同,是參數和方法體都為空的構造方法。如果在類中有顯式地定義構造方法,則系統將不再提供默認的構造方法。在一個類體中,構造方法可以有多個。(6)創建對象時,構造方法實參的個數和類型應與類中定義的構造方法形參的個數和類型相一致。3.3對象【例3-4】在類體中顯式地定義構造方法,創建對象時使用這個構造方法。3.3對象3.3對象publicclassExample3_4{ publicfinalfloatPI=3.14f;//定義常量PI privatedoubler=2;//定義圓的半徑 publicExample3_4(floatradius){//聲明帶有一個參數的構造函數 r=radius; }//構造函數結束 publicdoublegetArea(){//求圓的面積方法 doublearea=PI*r*r;//直接調用本類中的成員變量r和PI returnarea;//方法的返回值為double類型 } publicvoidgetCircum(){//求圓的周長方法 doublec=2*PI*r; System.out.println("圓的周長為"+c); }
publicstaticvoidmain(Stringargs[]){ Example3_4c2=newExample3_4(10); //調用構造方法創建類的對象,并賦值給類的引用c2 Example3_4c3=newExample3_4(20); //調用構造方法創建類的對象,并賦值給類的引用c3 System.out.println("對象c2的半徑為"+c2.r); //輸出對象c2的半徑 System.out.println("對象c3的半徑為"+c3.r); //輸出對象c3的半徑 doublea=c2.getArea();//通過對象來調用類中的成員方法 doubleb=c3.getArea();//通過對象來調用類中的成員方法 System.out.println("對象c2的面積為"+a); //輸出對象c2的面積 System.out.println("對象c3的面積為"+b); //輸出對象c3的面積 }}3.3.4對象初始化過程在創建對象的時候,使用new關鍵字調用構造方法對對象進行初始化。構造方法的作用是在創建對象時,由系統調用,完成對對象的初始化并為各個對象的數據成員賦初值。對象初始化分為三個步驟為引用分配存儲空間為對象分配存儲空間將對象的首地址放到引用中3.3對象1.為引用分配存儲空間例如Example3_5c2;此語句將為引用c2分配存儲空間。2.為對象分配空間newExample3_5(10);表示使用new關鍵字在內存中開辟一個新的空間,存儲對象。對象的各個成員變量的值,首先取該種數據類型的默認值,例如類Example3_5中,該對象的成員變量r的默認值是0.0。其次,如果成員變量在定義時候已經被賦初值,那么該成員變量的值是初始值,否則直接調用構造方法給成員變量賦值。在類Example3_5中,該對象的成員變量r的初始值是2。最后,執行構造方法的語句,將成員變量r的值修改為10。因此,對象newExample3_5(10)的成員變量r的值是10。3.3對象3.將對象的首地址放到引用中語句“c2=newExample3_5(10);”表示將對象newExample3_5(10)的首地址放入引用c2中。3.3對象【例3-5】對象的初始化。3.3對象【例3-5】對象的初始化。3.3對象publicclassExample3_5{ publicfinalfloatPI=3.14f;//定義常量PI privatedoubler=2;//定義圓的半徑 publicExample3_5(){//構造函數 System.out.println("執行構造函數"); } publicdoublegetArea(){//求圓的面積方法 doublearea=PI*r*r;//直接調用本類中的成員變量r和PI returnarea; } publicvoidgetCircum(){//求圓的周長方法 doublec=2*PI*r; System.out.println("圓的周長為"+c); }
publicstaticvoidmain(Stringargs[]){ Example3_5c2=newExample3_5(); //創建類的對象,并賦值給類的引用c2 Example3_5c3=newExample3_5(); //創建類的對象,并賦值給類的引用c3 System.out.println("對象c2存儲的地址為"+c2); //輸出c2中存儲的內容 System.out.println("對象c3存儲的地址為"+c3); //輸出c3中存儲的內容 System.out.println("圓的半徑的值為"+c2.r); //成員變量的值是初值 c2.r=10;//給對象的成員變量重新賦值 System.out.println("重新賦值后圓的半徑的值為"+c2.r); doublea=c2.getArea();//通過對象來調用類中的方法, System.out.println("對象c2的面積為"+a); //輸出對象c2的面積 c2.getCircum();//調用求周長的方法 }}3.4.1包(package)大多數軟件系統很龐大,通常將類分組到包中來簡化系統管理。包中可以包含類和子包。由于編譯器為每個類生成一個字節碼文件,且文件名與類名相同,所以同名的類有可能發生沖突,需要包來管理類名空間。3.4源文件的布局與類的封裝1.語法形式package語句作為Java源文件的第一條語句,指明該文件中定義的類所在的包(若缺省該語句,則指定為無名包)。package語句的語法格式:3.4源文件的布局與類的封裝說明:(1)編譯器把包對應于文件系統的目錄管理。在package語句中,用“.”來指明目錄的層次。例如,引入java.awt包的語句“packagejava.awt;”表示指定這個包中的文件存儲在目錄classpath/java/awt下。(2)包層次的根目錄path是由環境變量classpath來確定的。classpath是class文件存放的默認路徑,是用戶在配置環境變量的時候設置的。(3)如果一個源文件中有包聲明,則必須在源文件的開始處聲明。它的前面只能有空白和注釋,不能有其他語句。一個源文件中最多只允許聲明一個包,并且它要管理全部源文件。3.4源文件的布局與類的封裝2.Java中常用的類包3.4源文件的布局與類的封裝3.4.2引入類(import)在使用包時,要用import語句告知編譯器在哪里可以找到對應的類。為了使用Java系統提供的類和用戶自定義的類,需要使用import語句來引入類。事實上,包的名稱形成包內的類的一部分類名。1.import語句的語法格式3.4源文件的布局與類的封裝2.import語句的應用在使用包聲明時,不必導入相同的包或其他包內的任何元素。import語句的作用是使當前類能訪問其他包中的類。import語句指定要訪問的類。例如,只想使用java.util包的List類,則可以使用語句:
如果想使用包中所有的類,可以使用語句:使用import語句可以使程序員在源程序中使用短類名,除此之外沒有其他含義。一條import語句不會導致編譯器在內存中裝載任何附加內容。無論是否使用帶“*”的import語句,其對類文件及其運行效率均沒有任何影響。3.4源文件的布局與類的封裝3.4.3Java的源文件布局一個Java的源文件是以.java為擴展名的文件。Java源文件的基本格式:其中,包聲明和導入聲明可以省略,一個源文件中可以包含一個或多個類聲明。任何導入聲明必須位于所有的類聲明之前。若使用包聲明,則其必須位于類聲明和導入聲明之前,并且只能有一個。導入聲明則可以有多個。源文件中可以包括多個類聲明,但是只有一個類可以被聲明為公有的,源文件的名稱必須與公有類聲明的名稱相同。如果源文件中不包含公有類聲明,那么源文件的名稱不受限制。然而,比較好的習慣是,每個類聲明都有一個源文件,并且文件名與類名相同。3.4源文件的布局與類的封裝3.4.4類的封裝類的封裝一般隱藏對象的屬性和實現細節,僅對外公開接口,控制程序中屬性的讀和修改的訪問級別。封裝就是將抽象得到的數據和行為(或功能)相結合,形成一個有機的整體,也就是將數據與操作數據的源代碼進行有機結合,形成“類”,其中數據和方法都是類的成員。封裝的目的是增強安全性和簡化編程,使用者不必了解具體的實現細節,而只需要通過外部接口,以特定的訪問權限來使用類的成員。封裝的大致原則是把屬性和方法的實現等隱藏,只對外提供簡捷的接口。3.4源文件的布局與類的封裝根據封裝的原則,使用者可以使用部分成員方法,不能訪問其他成員,Java通過對成員設置訪問權限來達到這個目的。Java設置了4種訪問權限來實現封裝。public(公有)default(默認)protected(保護)private(私有)3.4源文件的布局與類的封裝1.public類中的public成員,可以被所有的類訪問,在類的外部通過對象可以調用類的所有public成員。2.default類中不加任何訪問權限限定的成員屬于默認的(default)訪問狀態,default修飾的成員可以被這個類本身和同一個包中的類訪問。3.protected類中的protected成員,可被該類及其子類、同一個包中的所有其他的類訪問。4.private類中限定為private的成員,只能被這個類本身訪問,只可以在類的內部被本類的方法所訪問。下表列出了這些限定詞的作用范圍。3.4源文件的布局與類的封裝允許其他包中的程序訪問和修改的成員變量和方法可以使用public修飾;只允許同一個包中的其他類,以及該類及其子類訪問和修改的成員變量可以使用protected修飾;只允許同一個包中的其他類訪問和修改的成員變量可以使用default修飾;不允許其他類(內部類除外)訪問和修改的成員變量可以使用private修飾。3.4源文件的布局與類的封裝【例3-6】類的封裝舉例。
3.4源文件的布局與類的封裝classExample{publicfinalfloatPI=3.14f;//定義常量PIprivatedoubler=2;//定義圓的半徑publicdoublegetR(){ returnr;}publicvoidsetR(doubler){ this.r=r; }publicdoublegetArea(){//求圓的面積方法 doublearea=PI*r*r;//直接調用本類中的成員變量r和PI returnarea;}publicvoidgetCircum(){//求圓的周長方法 doublec=2*PI*r;//直接調用本類中的成員變量r和PI System.out.println("圓的周長為"+c);}}
publicclassExample3_6{ publicstaticvoidmain(Stringargs[]){ Examplec2=newExample(); //創建類的對象,并賦值給類的引用c2 Examplec3=newExample(); //創建類的對象,并賦值給類的引用c3 //c2.r=10;//調用成員變量。對象c2的成員變量r賦值為10 //c3.r=20;//調用成員變量。對象c3的成員變量r賦值為20 c2.setR(10); c3.setR(20); doublea=c2.getArea();//通過對象來調用類中的成員方法 doubleb=c3.getArea();//通過對象來調用類中的成員方法 System.out.println("對象c2的面積為"+a); //輸出對象c2的面積 System.out.println("對象c3的面積為"+b); //輸出對象c3的面積 } }
3.5.1參數匹配方法調用的語法格式:方法調用時的參數被稱為實參。實參可以是常量、變量或表達式。其中實參列表由定義的方法的形參的數量和數據類型來決定,實參的個數、順序、類型和形參要一一對應。方法被調用時,程序會到被調用的方法處運行,運行完成后回到調用處,被調用的方法有返回值就返回所需要的值,如果沒有返回值則將返回到調用處。3.5方法的調用【例3-7】方法調用的參數匹配。
3.5方法的調用publicclassExample3_7{booleanflag;//是否訂閱privatefloatprice;//價格booleansetFlag(){ System.out.println("執行setFlag()方法"); returntrue; } voidsetPrice(floatp){ System.out.println("執行setPrice(floatp)方法"); price=p; } publicvoidoutput(){ System.out.println("執行output()方法"); System.out.println("是否訂閱:"+flag+""+"價格:"+price); } publicstaticvoidmain(String[]args){ Example3_7b=newExample3_7(); System.out.println("調用之前:"); b.output(); b.setPrice(36.5F); b.flag=b.setFlag(); System.out.println("調用之后:"); b.output(); }}3.5.2參數傳遞1.基本數據類型數據傳遞基本數據類型數據傳遞又稱傳值調用或者值參傳遞。在方法調用時,實參把它的值傳遞給對應的形參,方法執行中形參值的改變不影響實參的值。3.5方法的調用【例3-8】基本數據類型數據傳遞。
3.5方法的調用publicclassExample3_8{ voidexchange(inta,intb){//定義普通方法,交換a、b的值 inttemp; temp=a; a=b; b=temp; } publicstaticvoidmain(String[]args){ inti=10; intj=100; Example3_8ref=newExample3_8(); System.out.println("\n調用之前:"+"i="+i+"j="+j); //調用前 ref.exchange(i,j);//調用exchange方法,13行 System.out.println("調用之后:"+"i="+i+"j="+j); //調用后 }}程序說明:在例3-8中,第13行,“ref.exchange(i,j);”語句,相當于將變量i中存儲的值和變量j中存儲的值,作為實參來使用,即“ref.exchange(10,100);”調用ref所引用的類Example3_8中的名字為exchange并且有兩個整型參數的方法。將第一個值10賦值給exchange()方法的第一個形參a,并將第二個值100賦給exchange()方法的第二個形參b,然后執行exchange()方法體的內容。方法執行結束后,跳轉回到主方法,程序繼續向下執行。調用前后,a和b的值發生了變化,而i和j的值并沒有發生改變。在Java中,基本數據類型的參數在方法調用時其傳遞方式是傳值,方法執行中形參值的改變對實參沒有影響。3.5方法的調用2.引用數據類型數據傳遞引用數據類型數據傳遞又稱傳地址調用。如果在方法中把引用數據類型的對象作為參數,那么在方法調用時,參數傳遞的是對象的引用(地址),即在方法調用時,實參把對對象的引用(地址)傳遞給形參,這時實參與形參指向同一個地址,即同一個對象。3.5方法的調用【例3-9】引用數據類型數據傳遞。
3.5方法的調用classBook{booleanflag;privatefloatprice;Book(booleanf,floatp){ flag=f; price=p;}voidchange(Booka_book,booleanf,floatp){ a_book.flag=f; a_book.price=p; } publicvoidoutput(){ System.out.println("是否訂閱:"+flag+""+"價格:"+price); }}publicclassExample3_9{ publicstaticvoidmain(String[]args){ Bookb=newBook(false,36.5f); System.out.println("調用之前");b.output();b.change(b,true,100f);//調用b類中的change方法System.out.println("調用之后");b.output();}}程序說明:在例3-9中,“b.change(b,true,100f);”語句,相當于將對象b、boolean型值true和float型值100f,作為實參賦給對象b所引用的Book類中的change(Booka_book,booleanf,floatp)方法。將b的值賦給第一個參數a_book,將boolean型值true賦給第二個參數f,將float型值100f賦給第三個參數p。然后執行change()方法體的內容。方法執行結束后,跳轉回到主方法,程序繼續向下執行。在Java中,調用方法如果傳遞的是一個對象(地址),則對形參的操作相當于對實參的操作,方法執行中形參值的改變將會影實參的值。3.5方法的調用【例3-10】定義兩個不同的方法,一個方法用來實現基本數據類型數據值的交換,另一個方法用來實現引用數據類型參數的傳遞。比較這兩個方法在調用前、后,數據是否發生變化。
3.5方法的調用classPassTest{ floatptValue; publicvoidchangeInt(intvalue){value=55;} publicvoidchangeObjValue(PassTestref){ ref.ptValue=99f;} }publicclassExample3_10{ publicstaticvoidmain(Stringargs[]){ Stringstr;intval=33; PassTestpt=newPassTest(); PassTestptnew=newPassTest(); System.out.println("\n調用之前val="+val); pt.changeInt(val); System.out.println("調用之后val="+val); pt.ptValue=101f; ptnew.ptValue=1000f; System.out.println("調用之前ptValue="+pt.ptValue); pt.changeObjValue(pt); System.out.println("調用之后ptValue="+pt.ptValue); }}3.5.3遞歸調用程序調用自身的編程技巧被稱為遞歸。遞歸作為一種算法,在程序設計語言中被廣泛應用。遞歸是一個過程或方法在其定義或說明中直接或間接調用自身的一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,只需少量的程序就可描述出解題過程所需要的多次重復計算,大大減少了程序的代碼量。遞歸的能力在于用有限的語句來定義對象的無限集合。一般來說,遞歸需要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。3.5方法的調用3.5方法的調用使用遞歸的方法通常可以完成諸如求數組中的最大數、求n個數的和、求n個整數的積、求n個整數的平均值、求n個自然數的最大公約數與最小公倍數等問題的求解。
【例3-11】遞歸方法的定義和調用過程。
3.5方法的調用publicclassExample3_11{ publiclongfac(intn){//遞歸方法的定義 if(n==1)//遞歸出口 return1; else returnn*fac(n-1); } publicstaticvoidmain(Stringargs[]){ Example3_11e=newExample3_11(); System.out.println("5!="+e.fac(5)); }}3.6類的繼承類的繼承就是從現有類的基礎上,派生出一個新的類。新派生的類自動具有了現有類的全部屬性和方法。新類繼承了原有的類,同時新類又加入了原有的類中所沒有的新的屬性和特征,可以說新類是對原有類的擴展。在繼承關系中,通常把被繼承的類稱為基類或父類,而把通過繼承產生的新類稱為派生類或子類。父類和子類之間是一般和具體、普遍和特殊的關系。
3.6類的繼承父類和子類的關系是相對而言的,一個子類也可以成為另一個類的父類。在實際的程序設計中,通常需要通過繼承和派生構建具有層次結構的類家族。交通工具類的層次如圖所示。一個類只有一個直接父類,稱為單重繼承,Java只支持單重繼承。
3.6.1子類的定義1.子類的聲明在Java類的聲明中,使用關鍵字extends實現繼承,由已有的父類派生子類。語法格式:3.6類的繼承說明(1)修飾符可以是public或缺省的。class是定義類的關鍵字。子類名是新定義的類的類名稱,是合法的Java標識符。extends是類的繼承關鍵字。父類名是已經定義了的類的名稱,父類可以是Java中提供的類,也可以是用戶自定義的類。例如:表示Student類是Person類的子類。定義中Student是新定義的子類,Person是已經定義過的父類。(2)在Java中,每個類都有自己的父類。如果一個類在定義時沒有聲明父類,那么它的父類默認為Object類;Object類是其他所有類的父類,是類層次的根。所有的類都擁有Object類定義的所有方法。3.6類的繼承說明(3)因為Java是單繼承,所以extends關鍵字后面有且只有一個父類名。(4)子類的類體定義子類自己的成員變量(屬性)和成員方法或重寫父類的方法。3.6類的繼承為了了解Java語言的繼承機制,先從一個簡單的例子開始學習。現在需要定義兩個類,一個類是Person類,具有的屬性為人員編號和年齡,具有的方法是吃飯和喝水。另一個類是Student類,具有的屬性為人員編號、年齡和學校編號,具有的方法是吃飯、喝水和學習。根據前面學的類定義知識,可以對Person類和Student類分別進行定義。3.6類的繼承3.6類的繼承Person類Student類通過分析代碼發現,在Student類中,重復定義了Person類的成員屬性和成員方法,同時又定義了Student類中特有的成員屬性和成員方法。這種定義并沒有面向對象編程所支持的代碼重用。根據面向對象的繼承機制,我們通過類的繼承關系,可以重新定義Student類。通過類的繼承,在子類中只需要定義子類增加的成員屬性和成員方法即可。3.6類的繼承【例3-12】類的繼承
應用。
3.6類的繼承classPerson{//Person類默認為Object類的子類 publicintid;//人員編號publicintage;//年齡voidsetValue(inti,inta){id=i;age=a;}publicvoideat(){System.out.println(id+"愛吃米飯!");}voiddrink(){System.out.println(id+"愛喝水!");}}classStudentextendsPerson{//類Student是Person類的子類,繼承了Person類的方法和成員。 publicintSchoolId;//學校編號;Student除了繼承Person的成員,還增加了自己的成員schoolIdpublicvoidstudy(){//在子類中定義學習的方法 System.out.println(id+"我要上課學習");}}publicclassExample3_12{//測試父子繼承關系中方法和成員變量的調用 publicstaticvoidmain(Stringargs[]){ Personp=newPerson(); Students=newStudent(); p.setValue(1,50);//父類的對象調用父類的方法 p.drink();//父類的對象調用父類的方法 p.eat();//父類的對象調用父類的方法 s.setValue(2,18);//子類的對象調用父類的方法 s.drink();//子類的對象調用父類的方法 s.eat();//子類的對象調用父類的方法 s.study();//子類的對象調用子類的方法 }}2.類的繼承機制(1)成員變量的繼承子類可以繼承父類的所有成員變量(即屬性),但是對于繼承的私有的成員變量,子類無法訪問和使用。如果希望父類的成員變量不被子類訪問,那么就將其聲明為私有的,這充分體現了面向對象編程的封裝原則。若子類的成員變量名與父類中的相同,則稱子類的成員變量覆蓋父類的成員變量。3.6類的繼承【例3-13】成員變量的繼承。
3.6類的繼承classA{ privateinti=10; intj=20; intk=30; voidprintA(){ System.out.println("A中的i="+i+";A中的j="+j+"; A中的k="+k); } }classBextendsA{ intj=50; //子類B中重新定義了成員變量j,隱藏了從父類繼承過來的成員變量j。 voidprintB(){ System.out.println("B中的j="+j+";A中的k="+k); //A類中的i在B類中無法被訪問 }}publicclassExample3_13{ publicstaticvoidmain(String[]args){ Aa=newA();Bb=newB(); a.printA(); b.printB(); }}(2)成員方法的繼承子類繼承父類的所有的成員方法,但是私有的成員方法不能直接使用。如果子類定義的成員方法與父類的相同,則稱子類的成員方法覆蓋父類的成員方法,即子類重新定義父類的同名方法。3.6類的繼承【例3-14】成員方法的繼承。
3.6類的繼承classA{ inti=5; voidsetValues(intj){i=j;} voidmyPrint(){System.out.println("執行A類中的myPrint()方法;i="+i);}}//A類定義結束classBextendsA{ voidmyPrint(){ //子類B中定義的myPrint()方法覆蓋了從父類中繼承過來的myPrint()方法System.out.println("執行B類中的myPrint()方法;i="+i);}}//B類定義結束publicclassExample3_14{ publicstaticvoidmain(String[]args){ Aa=newA(); Bb=newB(); a.setValues(100);b.setValues(200); a.myPrint();//調用A類中的方法 b.myPrint();//調用B類中的方法 }}(3)構造方法的繼承子類不能繼承父類的構造方法,但可以調用父類的構造方法。構造方法的三種調用方式:創建對象的時候使用new關鍵字來調用類中的構造方法。使用super關鍵字在子類構造方法中調用父類的構造方法。在本類的構造方法中使用this關鍵字來調用本類中其他的構造方法。3.6類的繼承①super關鍵字可以使用super關鍵字在子類構造方法中調用父類的構造方法。語法格式:該語句在使用時必須作為子類構造方法的第一條語句。在類的構造方法中,如果沒有使用“this([參數列表]);”或“super([參數列表]);”語句,系統將自動調用super(),即默認在構造方法的第一行添加“super();”語句。若系統中自動調用super(),而父類當中并沒有定義無參的構造方法,則程序編譯出錯。3.6類的繼承【例3-15】使用super關鍵字
調用構造方法。
3.6類的繼承classA{ inti;A(){System.out.println("執行構造函數A()");}A(intm){ i=m; System.out.println("執行構造函數A(intm)"); }}classBextendsA{ intj=50; B(){//默認添加語句super();System.out.println("執行構造函數B()"); } B(intk){ super(k); //顯式調用父類有一個參數的構造方法,必須是構造函數的第一句 j=k;//給成員變量賦值 System.out.println("執行構造函數B(intk)"); }}publicclassExample3_15{ publicstaticvoidmain(String[]args){ Aa=newA();//創建A類對象 Aa2=newA(3);//創建A類對象 Bb=newB();//創建B類對象 Bb2=newB(2);//創建B類對象 }}①super關鍵字如果子類在繼承父類時,子類中重新定義了和父類中一樣的成員變量和成員方法,那么創建子類的對象時,將會調用子類中的成員變量和成員方法。如果需要在子類中調用父類被隱藏的成員變量或被重寫的成員方法,則可以使用super關鍵字,語法格式如下。3.6類的繼承【例3-16】使用super關鍵字
調用成員變量和
成員方法。
3.6類的繼承classA{ privateinti=20; intj=30; voidmyPrint(){ System.out.println("A類中的i="+i+";A類中的j="+j); }}classBextendsA{ intj=50; voidmyPrint(){//子類的方法覆蓋了父類的方法 super.myPrint();//調用本類的父類的myPrint()方法 System.out.println("A類中的j="+super.j+";B類中的j="+j); }}publicclassExample3_16{ publicstaticvoidmain(String[]args){ Aa=newA(); Bb=newB(); a.myPrint(); b.myPrint(); }}②this關鍵字this關鍵字表示當前類的內部對象,常用于當成員變量與局部變量同名時引用成員,或者將當前對象作為參數傳遞給另一個方法。使用this關鍵字可以訪問所有級別的成員變量和成員方法。this關鍵字的使用和類的外部對象訪問類的成員變量和成員方法的規則一致。this關鍵字的語法格式如下。this關鍵字在實例方法中通常被省略,除非實例方法中包含與成員變量同名的局部變量時,訪問成員變量才需要使用this關鍵字。3.6類的繼承下面的程序使用了this關鍵字調用成員變量和成員方法。當一個類體中包含多個構造方法的時候(構造方法形成重載),如果其中一個構造方法要調用本類中其他的構造方法,那么就使用this關鍵字,使用“this([參數列表]);”的語法格式可以完成調用同類其他構造方法的功能,且該語句只能作為構造方法的第一條語句。3.6類的繼承【例3-17】使用this關鍵字調用構造方法。
3.6類的繼承classPerson{ publicintid;//人員編號 publicintage;//年齡 Person(){ this(3,60);//調用本類中其他的構造方法 System.out.println("執行Person()構造方法"); } Person(intid,intage){ this.id=id;//給成員變量賦值,this關鍵字不能省略 this.age=age;//給成員變量賦值,this關鍵字不能省略 System.out.println("執行Person(intid,intage)構造方法"); } voidsetValue(inti,inta){ id=i;//給成員變量賦值,id前面省略this關鍵字 this.age=a;//給成員變量賦值,this關鍵字可以省略} voiddrink(){ System.out.println(id+"愛喝水!"); }}publicclassExample3_17{ publicstaticvoidmain(Stringargs[]){ System.out.println("調用無參的構造方法創建第一個對象"); Personp=newPerson();//創建Person類對象 System.out.println("調用兩個參數構造方法創建第二個對象"); Personp2=newPerson(4,80);//創建Person類對象 }}3.6.2類的多態多態(polymorphism)即一個名稱具有多種語義。當一個父類中存在多個子類,并且每個子類都重寫了父類中的某個方法時,父類中的該方法在不同的子類中就出現了不同的行為,這就是多態的一種表現形式。類的多態表現為方法的多態:方法的重載(overload)方法的覆蓋(override)3.6類的繼承1.方法的重載方法的重載是在同一個類中,有多個方法的名稱相同,但是方法的參數列表的不同。參數列表的不同是指參數的個數不同,或者參數的個數相同,但對應參數的數據類型不同。voidsetValue(){/*方法體*/}voidsetValue(inti){/*方法體*/}方法的返回值是否相同不能構成重載的條件。在調用同名的方法時,系統在程序執行過程中會根據實參的個數與類型去匹配相應的方法,從而決定調用的是哪一個方法。3.6類的繼承【例3-18】測試方法的重載。
3.6類的繼承classTestMax{ intIMax(inti,intj){//求兩個整數的最大值 System.out.println("執行IMax(inti,intj)方法"); if(i>=j){returni;} else{returnj;} }intIMax(inti,intj,intk){//求三個整數的最大值 System.out.println("執行IMax(inti,intj,intk)");if(i>=j){ if(i>=k){returni;} else{returnk;} }else{ if(j>=k){returnj;}else{ returnk;} }}}publicclassExample3_18{publicstaticvoidmain(String[]args){ TestMaxt=newTestMax(); System.out.println("兩個數最大值為"+t.IMax(3,5)); System.out.println("三個數最大值"+t.IMax(10,7,12));}}2.方法的覆蓋方法的覆蓋也稱為重寫,是指子類創建了同父類的方法名、返回值類型和參數列表完全相同的方法,我們認為子類的方法覆蓋了父類的方法。方法的覆蓋與繼承有密切關系,體現了子類補充或改變父類方法的能力。覆蓋使一個方法在不同子類中表現為不同行為。3.6類的繼承(1)方法覆蓋的原則子類方法與父類被覆蓋的方法的名稱、返回值類型和參數列表完全相同。不能覆蓋父類中final或static關鍵字修飾的方法。覆蓋方法的可訪問性不能低于被覆蓋的方法。3.6類的繼承例如,在父類中定義如下方法:如果子類中定義同名方法:publicvoidsetValues(inti){intj=i;};
子類的setValues()方法因為和父類中的setValues()方法名稱、返回值類型和參數列表完全相同,并且訪問修飾符的訪問范圍也相同,所以形成了方法的覆蓋。但是若在子類中的方法定義成“voidsetValues(inti){intj=i;};”則會出現錯誤。因為雖然子類中的setValues()方法名稱、返回值類型和參數列表與父類聲明的完全相同,但是子類的setValues()方法的訪問修飾符為default,比父類當中的public訪問性更弱,所以沒有形成子類和父類之間的方法覆蓋。3.6類的繼承(2)覆蓋方法的調用在方法的調用上,如果子類中的方法覆蓋了父類中的方法,那么子類不能繼承父類中被覆蓋的方法,子類的對象將調用子類中重寫的方法。如果子類想調用父類中被覆蓋了的方法,只能使用“super.成員方法([參數列表]);”語句。創建父類的對象將調用父類的方法。3.6類的繼承【例3-19】方法的覆蓋與調用。
3.6類的繼承classA{//定義類Apublicintx,y;//定義成員變量A(inta,intb){x=a;y=b;}//構造方法publicvoiddisplay(){//父類聲明的方法intz;z=x+y;System.out.println("A類的display()方法"+z);}}classBextendsA{//定義子類BB(inta,intb){//構造方法super(a,b);//調用超類的構造方法} publicvoiddisplay(){//重新定義方法,子類方法覆蓋了超類方法intz;z=x*y;System.out.println("B類的display()方法"+z);}}classCextendsB{//定義子類CC(intx,inty){super(x,y);}//構造方法,調用超類構造方法}publicclassExample3_19{publicstaticvoidmain(Stringargs[]){An1=newA(7,14);//分別創建三個類的對象Bn2=newB(7,14);Cn3=newC(7,14);n1.display();//三個對象都調用display方法n2.display();n3.display();}}3.子類對象和父類對象間的轉換一個子類的對象也是一個父類的對象,但是一個父類的對象不一定是一個子類的對象。例如,Person類代表人類,Student類代表學生類,Student類是Person類的子類。任意一個學生一定是一個人,但是任意一個人不一定就是一個學生。創建一個子類的對象,則該對象也一定是父類的對象,就可以把這個對象的引用賦值給父類的對象。反之,若把子類的對象賦值給父類的對象的引用,則不一定成立。若想把子類的對象合法地賦給父類的對象,則必須做強制類型轉換。如下面語句:Personp=newStudent();一定是成立的。Students=(Student)newPerson();才成立。3.6類的繼承對象的轉換只能在父類和子類之間進行。測試類之間是否有繼承關系,需要使用instanceof運算符。用來判斷前、后是否是同類。若對象名是該類或該類的子類對象,則返回值為真;否則返回值為假。3.6類的繼承【例3-20】測試子類對象和父類對象間的轉換。
3.6類的繼承classPerson{ protectedStringname; protectedintage; publicPerson(Stringn1,inta1){ name=n1;age=a1; }//構造方法 publicStringtoString(){ return+","+this.age; } publicvoidprint(){System.out.println("本類名="+this.getClass().getName()+""+"超類名="+this.getClass().getSuperclass().getName()+"");Objects1=this;if(s1instanceofPerson)Syst
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025建筑材料供應合作合同
- 2025企業勞動派遣合同范本
- 2025塔吊租賃和維護的合同書
- 2025建筑外墻仿石漆施工合同 安全施工協議
- 2025適宜用于商業注冊的辦公室租賃合同
- 土建工程施工合同補充協議
- 裝飾畫制作合同范本
- 起重機轉讓合同范本
- 寵物美容洗澡協議書
- 共享商圈協議書范本
- 《肌力訓練》課件
- 全媒體運營師-國家職業標準(2023年版)
- 招標投標法培訓課件
- GLB-2防孤島保護裝置試驗報告
- 中鐵員工內退管理辦法
- 皮膚科玫瑰痤瘡的臨床表現和診斷學習培訓課件
- 高考日語復習:日語形容詞用法專項課件
- 馬克思主義與社會科學方法論概述(課件)
- 城市道路養護技術規程
- 2023年國家藥監局直屬單位公開招聘筆試參考題庫(共500題)答案詳解版
- JGT116-2012 聚碳酸酯(PC)中空板
評論
0/150
提交評論