4.1 面向?qū)ο蠡靖拍?br/>4.1.1 對(duì)象
對(duì)象:相關(guān)數(shù)據(jù)和方法的集合
4.1.2 封裝
封裝的含義是把類設(shè)計(jì)成一個(gè)黑箱,使用者只能看見(jiàn)類中定義的公共方法,而看不到方法實(shí)現(xiàn)的細(xì)節(jié),也不能直接對(duì)類的數(shù)據(jù)進(jìn)行操作,迫使用戶通過(guò)接口去訪問(wèn)數(shù)據(jù)。
封裝是一種信息隱蔽技術(shù),封裝的定義為:
(1)一個(gè)清楚的邊界;所有對(duì)象的內(nèi)部軟件的范圍被限定在這個(gè)邊界內(nèi);
?。?)一個(gè)接口:這個(gè)接口描述該對(duì)象和其他對(duì)象之間的相互作用;
(3)受保護(hù)的內(nèi)部實(shí)現(xiàn):這個(gè)實(shí)現(xiàn)給出了由軟件對(duì)象提供的功能的細(xì)節(jié),實(shí)現(xiàn)細(xì)節(jié)不能在定義這個(gè)對(duì)象的類的外面訪問(wèn)。
4.1.3 消息
對(duì)象的行為由方法來(lái)實(shí)現(xiàn),消息傳遞是對(duì)象之間進(jìn)行交互的主要方式。
構(gòu)成消息的3個(gè)要素是:接收消息的對(duì)象、接收消息后進(jìn)行處理的方法和方法所需要的參數(shù)。
4.1.4 類
類是一種復(fù)雜的數(shù)據(jù)類型,是將不同類型的數(shù)據(jù)和這些數(shù)據(jù)相關(guān)的運(yùn)算(即方法)封裝在一起的集合體。它是對(duì)所要處理的問(wèn)題的抽象描述。
4.1.5 繼承
一個(gè)類的上一層稱為父類,而下一層稱為子類,一個(gè)類可以繼承其父類的變量和方法,且這種繼承具有傳遞性。
4.1.6 接口
接口可以看成是為兩個(gè)不相關(guān)的提供交流途徑的工具,是一個(gè)包含方法定義和常量值的集合。
Java不支持多繼承,子類只能有一個(gè)父類,有時(shí)需要使用其他類中的方法,但又無(wú)法直接繼承,這時(shí)可以使用接口技術(shù)。
接口不需要建立繼承關(guān)系,就可以使兩個(gè)不相關(guān)的類進(jìn)行交互。
體現(xiàn)面向?qū)ο笏枷氲某绦颍阂?jiàn)P60
4.2 Java的類與對(duì)象
Java程序的所有數(shù)據(jù)類型都是用類來(lái)實(shí)現(xiàn)的,Java語(yǔ)言是建立在類這個(gè)邏輯結(jié)構(gòu)之上的,所以Java是一種完全面對(duì)象的程序設(shè)計(jì)語(yǔ)言。類是Java的核心,Java程序都由類組成,一個(gè)程序至少包含一個(gè)類,也可以包含多個(gè)類。對(duì)象是類的實(shí)例,Java程序中可以使用標(biāo)識(shí)符表示對(duì)象,并通過(guò)對(duì)象引用類中的變量和方法。
Java程序員的任務(wù)就是設(shè)計(jì)出類和對(duì)象來(lái)解決實(shí)際問(wèn)題。創(chuàng)建類時(shí)既可以從父類繼承,也可以自行定義。
4.2.1 類的創(chuàng)建
格式: [修飾符] <class> <類名> [extends 父類] [implements接口]
{ 類體(成員變量和成員方法) }
修飾符:指明類在使用時(shí)所受到的限制,包括類訪問(wèn)權(quán)限[public]和其他特性[abstract],[final]
例:public class C1 { …… }
public class C2 extends Applet implements ActionListener
{……}
1.class <類名>
告訴編譯器這是一個(gè)類
2.Public(公共的)
在沒(méi)有任何修飾符的默認(rèn)情況下,類只能被同一個(gè)源程序文件或同一個(gè)包中的其他類使用,加上public后,該類可以被任何包中的類使用,稱為公共類。
注意:在同一個(gè)源程序文件中不能出現(xiàn)兩個(gè)及以上的public類,否則編譯器會(huì)告訴你將第二個(gè)public類放在另一個(gè)文件中。
3.a(chǎn)bstract(抽象的)
abstract說(shuō)明的類稱為抽象類,不能用它實(shí)例化一個(gè)對(duì)象,它只能被繼承,abstract方法是不含代碼的方法,需要以后的子類中重載實(shí)現(xiàn),abstract類的子類必須實(shí)例化(實(shí)現(xiàn))abstract方法,或?qū)⒆约阂猜暶鳛閍bstract。這對(duì)于定義概念是有用的。
4.final(最終的)
final說(shuō)明的類稱為最終類,最終類不能被繼承
Java中的String和Array類就是一個(gè)final類
注意:final和abstract不能同時(shí)修飾一個(gè)類(出錯(cuò)),這樣的類沒(méi)有意義
無(wú)修飾符是默認(rèn)方式,即不使用上述三種修飾符。因此它們的優(yōu)勢(shì)和限制都沒(méi)有作用,無(wú)修飾符的類可以被其他類訪問(wèn)和繼承,但只有在相同程序包中的那些對(duì)象才可能使用這樣的類。
5.extends(繼承)父類名
extends告訴編譯器創(chuàng)建的類是從父類繼承下來(lái)的子類,父類必須是Java系統(tǒng)類或已經(jīng)定義的類。
從父類繼承,可以提高代碼重用性,不必從頭開(kāi)始設(shè)計(jì)程序。
6.implements(實(shí)現(xiàn))接口名
implements告訴編譯器類實(shí)現(xiàn)的接口,接口必須有定義,一般為系統(tǒng)類。
接口是消息傳遞的通道,通過(guò)接口,消息才能傳遞到處理方法中進(jìn)行處理。implements說(shuō)明你的類可以實(shí)現(xiàn)的一個(gè)或多個(gè)接口,如果有多個(gè)接口,要用逗號(hào)分隔。
例:import java.awt.*;
import java.applet.*;
public class ch3 extends Applet{
public void paint(Graphics g) {
g.drawString("Hello Java!I love you^_^",25,25); } }
<html>
<head>
<title>Hello Java Applet測(cè)試</title>
</head>
<APPLET code=ch3.class width=200 height=40>
抱歉,你的瀏覽器不支持JAVA APPLET┅
</APPLET>
</html>
4.2.2 對(duì)象的創(chuàng)建
類的對(duì)象的模板,Java運(yùn)行應(yīng)該是用類創(chuàng)建實(shí)例化對(duì)象。
一旦任務(wù)完成,對(duì)象就會(huì)被垃圾收集器收回,完成它從創(chuàng)建、使用到清除。
見(jiàn)P66 例4.3
1.創(chuàng)建對(duì)象與構(gòu)造方法
創(chuàng)建對(duì)象格式: 類名 對(duì)象名=new 類名([參數(shù)]) ;
說(shuō)明:(1)運(yùn)算符new為對(duì)象分配內(nèi)存空間;
?。?)生成對(duì)象的最后一步是執(zhí)行構(gòu)造方法;
?。?)創(chuàng)建對(duì)象相當(dāng)于定義一個(gè)變量,即分兩步進(jìn)行。
創(chuàng)建對(duì)象分成兩步: 類名 對(duì)象名 ;
對(duì)象名=new 類名([參數(shù)]) ;
2.對(duì)象初始化的說(shuō)明
?。?)系統(tǒng)如何對(duì)變量初始化
當(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類型設(shè)置初值為0;float類型變量初值為0.0f;double類型變量初值為0.0;char字符型變量為’u\0000’;boolean邏輯變量初值為false;引用類型初值勤為null。
(2)構(gòu)造方法的作用與構(gòu)成
new操作符為對(duì)象分配內(nèi)存后將調(diào)用類的構(gòu)造方法確定對(duì)象的初始狀態(tài),初始化所有變量。
構(gòu)造方法功能:創(chuàng)建對(duì)象時(shí),用給定的值,將對(duì)象初始化
構(gòu)造方法特點(diǎn):
?。?)構(gòu)造方法名與類名相同,且不指定類型說(shuō)明;
?。?)可以重載,即可以定義多個(gè)參數(shù)個(gè)數(shù)不同的函數(shù),系統(tǒng)可以根據(jù)參數(shù)的不同,自動(dòng)調(diào)用正確的構(gòu)造方法;
?。?)程序中不能直接調(diào)用構(gòu)造函數(shù),在創(chuàng)建對(duì)象時(shí)系統(tǒng)自動(dòng);
?。?)可以不設(shè)計(jì)構(gòu)造方法,若在初始化時(shí)還要執(zhí)行一些其他命令,就必須設(shè)計(jì)構(gòu)造方法,因?yàn)镴ava規(guī)定命令語(yǔ)句不能出現(xiàn)在類體中,只能放在方法中。
重載:參數(shù)不同可以是數(shù)量不同,類型不同,或兩者都不同,但重載方法必須有相同的方法名和相同的返回類型。
例:class ABC{
public ABC( ) {……} // 無(wú)參數(shù)構(gòu)造方法
public ABC(int a, int b ) {……} // 帶兩個(gè)參數(shù)構(gòu)造方法
public ABC(String a ) {……} // 帶一個(gè)個(gè)參數(shù)構(gòu)造方法
public int ABC(int a) {……} // 錯(cuò),構(gòu)造方法不能有類型返回值
public void ABC( ) {……} // 錯(cuò),構(gòu)造方法不能有類型返回值
}
例:public class SC{
public static void main(String args[]){
sc1 a=new sc1( ) ;
sc1 b=new sc1("練習(xí)") ;
System.out.println("程序結(jié)束!");} }
class sc1{
public sc1( ) {System.out.print("開(kāi)始");}
public sc1(String z) {System.out.println(z);} }
運(yùn)行結(jié)果:開(kāi)始練習(xí)
程序結(jié)束
3.對(duì)象的使用
格式:<對(duì)象名>.<變量名>
<對(duì)象名>.<方法名([參數(shù)])>
例:SC a =new SC( ) //SC是已定義的類,a則是新建的SC對(duì)象
a.bian=23 // 將對(duì)象a的變量bian賦值23
a.Fan( ) // 調(diào)用對(duì)象a的方法Fan
例:class parents{
private String name[]=new String[5];
parents(String s[])
{for(int i=0;i<s.length;i++)
name[i]=s[i]; }
public void showname()
{for(int i=0;i<s.length;i++)
System.out.print(name[i]+” ”);
}}
class SC
{ public static void main(String args[])
{ String name[]={"Zhang","Wang","Li"};
parents p=parents(name);
p.showname()
}}
結(jié)果: 輸出 Zhang Wang Li
例:public class NewClass{
public static void main(String args[]){
G k=new G();
k.setK(8);
int y=k.getK();
System.out.println(“y=”+y); }
}}
class G{
private int k;
public void setK(int x){
k=x; }
public int getK(){ return k;}
}}
運(yùn)行結(jié)果: y=8
4.清除對(duì)象
Java引入了新的內(nèi)存管理機(jī)制,由Java虛擬機(jī)擔(dān)當(dāng)垃圾收集器的工作。你可以任意創(chuàng)建對(duì)象,而不用擔(dān)心如何清除它們,垃圾收集器會(huì)自動(dòng)清除它們。
如果要明確地清除一個(gè)對(duì)象,可以自行清除它。只需把一個(gè)空值賦給這個(gè)對(duì)象引用即可。如
SC a =new SC( )
……
a=null // 將對(duì)象a從內(nèi)存中清除
5.析構(gòu)方法(finalize)(補(bǔ)充)
析構(gòu)方法(finalize)與構(gòu)造方法相對(duì)應(yīng),當(dāng)對(duì)象已經(jīng)無(wú)用,需要清除時(shí),編譯器將自動(dòng)調(diào)用對(duì)象的finalize方法。析構(gòu)方法一般是做一些清除工作,如關(guān)閉打開(kāi)的文件等,但不能執(zhí)行用戶輸入操作或與其他對(duì)象進(jìn)行交互。
如 class ABC{
……
protected|public void finalize( )
{ // do some cleanup code } }
4.3 成員變量與封裝
成員變量描述了類和對(duì)象的狀態(tài),有時(shí)也稱為屬性、數(shù)據(jù)或域
4.3.1 成員變量的聲明
成員變量的聲明必須放在類體中,通常是在成員方法之前。在方法中聲明的變量不是成員變量,而是方法的局部變量,二者是有區(qū)別的。
例:見(jiàn)P71
4.3.2 成員變量的修飾
聲明變量格式:[public][private][protected][package] //訪問(wèn)控制修飾符
[static][final][transient][volatile]<數(shù)據(jù)類型><成員變量名稱>
1.訪問(wèn)控制權(quán)限
表: 修飾符的作用范圍
修飾符
類
子類
包
所有類和包
Public
√
√
√
√
Private
√
Protected
√
√
√
package(默認(rèn))
√
√
?。?)public(公共)變量
由public修飾的變量稱為公共變量,可被任何包中的任何類訪問(wèn)
?。?)private(私有)變量
由private修飾的變量稱為私有變量,只能被聲明它的類所使用
?。?)protected(受保護(hù))變量
由protected修飾的變量稱為受保護(hù)變量,可被聲明它的類和派生的子類以及同一個(gè)包中的類訪問(wèn)
?。?)package(包)變量
由package修飾的變量稱為包變量,沒(méi)有修飾符時(shí),默認(rèn)變量即是包變量,可被聲明它的類和同一個(gè)包中的其他類(包括派生子類)訪問(wèn)
2.static(靜態(tài))變量
由static修飾的變量稱為靜態(tài)變量,靜態(tài)變量是類固有的,可以直接引用(方法:類名.靜態(tài)變量名),其他成員變量?jī)H僅被聲明,只有等到生成實(shí)例對(duì)象后才存在,才可以被引用,靜態(tài)變量也稱為類變量,非靜態(tài)變量稱為實(shí)例變量。相應(yīng)地靜態(tài)方法稱為類方法,非靜態(tài)方法稱為實(shí)例方法。
靜態(tài)變量可被此類創(chuàng)建的所有對(duì)象共享。
例:class Car {
String 車型;
static int 價(jià)格;
public Car(String 車型, int 價(jià)格)
{ this.車型=車型;
this.價(jià)格=價(jià)格; }
public void 介紹(String s)
{System.out.println(s+"\t"+車型+"\t"+"價(jià)格 "+價(jià)格);} }
public class SC{
public static void main(String args[]){
Car 奔馳=new Car("越野車",400000) ;
奔馳.介紹("奔馳");
Car 紅旗=new Car("轎車",200000) ;
紅旗.介紹("紅旗");
奔馳.介紹("奔馳"); }}
運(yùn)行結(jié)果:奔馳 越野車 價(jià)格 400000
紅旗 轎車 價(jià)格 200000
奔馳 越野車 價(jià)格 200000
3.final(最終)變量
一旦成員變量被聲明為final,在程序運(yùn)行中將不能被改變,即是一個(gè)常量。
如: final int I=5 ;
final double PI=3.1415926 ;
4.transient(過(guò)渡)變量(不做要求)
Java目前對(duì)transient修飾符沒(méi)有明確說(shuō)明,它一般用在對(duì)象序列化(object serialization)上,說(shuō)明成員變量不許被序列化。
5.volatile(易失)變量(不做要求)
volatile聲明的成員變量為易失變量,用來(lái)防止編譯器對(duì)該成員進(jìn)行某種優(yōu)化。這是Java語(yǔ)言的高級(jí)特性,僅被少數(shù)程序員使用。
4.4 成員方法
對(duì)象的行為由類的方法實(shí)現(xiàn),實(shí)際上,方法就是完成某種功能的程序塊。從功能上講,方法和函數(shù)十分類似。
4.4.1 成員方法的設(shè)計(jì)
例:見(jiàn)P77
4.4.2 成員方法的聲明與修飾
格式:[public][private][protected][package][static][final][abstract][native]
[synchronized] 返回值類型 方法名(參數(shù)表)[throws 異常類型]
說(shuō)明:[public][private][protected][package][static] [final]與成員變量功能相同,都是定義方法訪問(wèn)權(quán)限。
1.final(最終)方法
方法被聲明為最終方法后,將不能被子類覆蓋,即最終方法,能被子類繼承和使用但不能在子類中修改或重新定義它。這種修飾可以保護(hù)一些重要的方法不被修改。
在OOP中,子類可以把父類的方法重新定義,使之具有新功能但又和父類的方法同名、同參數(shù)、同返回值,這種情況稱為方法覆蓋(override)。
2.a(chǎn)bstract(抽象)方法
抽象方法即無(wú)方法體的方法,抽象方法不能出現(xiàn)在非抽象類中。
為什么要使用抽象類和抽象方法呢?一個(gè)抽象類可以定義一個(gè)統(tǒng)一的編程接口,使其子類表現(xiàn)出共同的狀態(tài)和行為,但各自細(xì)節(jié)是不同的。子類共有的行為由抽象類中的抽象方法來(lái)約束,而子類行為的具體細(xì)節(jié)則通過(guò)抽象方法的覆蓋來(lái)實(shí)現(xiàn)。這種機(jī)制可增加編程的靈活性,也是OOP繼承樹(shù)的衍生基礎(chǔ)。
3.native(本地)方法(不做要求)
用其他語(yǔ)言編寫的方法在Java中稱為本地方法。
SDK提供了Java本地接口JNI(Java Native Interface),使得Java虛擬機(jī)能運(yùn)行嵌入在Java程序中的其他語(yǔ)言,這些語(yǔ)言包括C/C++ ,F(xiàn)ORTRAN ,匯編語(yǔ)言等。
4.synchronized(同步)方法
同步方法用于多線程編程。多線程在運(yùn)行時(shí),要能會(huì)同時(shí)存取一個(gè)數(shù)據(jù)。為避免數(shù)據(jù)的不一致性,應(yīng)將方法聲明為同步方法,對(duì)數(shù)據(jù)進(jìn)行加鎖。
5.throws(異常)類型
程序在運(yùn)行時(shí)可能發(fā)生異?,F(xiàn)象。每一個(gè)異常對(duì)象都對(duì)應(yīng)著一個(gè)異常類,如果暫時(shí)不希望方法處理某種異常,可將其拋出,使程序得以繼續(xù)運(yùn)行。
如:protected void SC( ) throws IOException ; //輸入輸出異常拋出
6.返回值類型
Java要求一個(gè)方法必須聲明它的返回值類型,如果方法沒(méi)有返回值就用關(guān)鍵字void作為返回值類型。否則應(yīng)使用基本數(shù)據(jù)類型或?qū)ο箢愋驼f(shuō)明返回值類型。
如: public void SC( ) ; // 沒(méi)有返回值
int getx( ) ; // 返回值是int類型
private String abc( ) ; // 返回值是String類型
public static double du( ) ; // 返回值是double類型
protected Object oj( ) ; // 返回值是Object類型
7.方法名
方法名要以是任何有效的Java標(biāo)識(shí)符,方法名可以和成員變量同名,也可以和成員方法同名。同一個(gè)類中的方法同名現(xiàn)象在OOP中稱為方法重載(overload)。
如: void SC( ) {……}
void SC(int a ) {……}
void SC(int a, int b) {……}
void SC(double a, int b) {……}
8.參數(shù)表
方法的調(diào)用者正是通過(guò)參數(shù)表將外部消息傳遞給方法的。在參數(shù)表中要聲明參數(shù)的類型,并用逗號(hào)分隔多個(gè)參數(shù)。
4.4.3 方法體
方法體包含在一對(duì)大括號(hào)中,即使方法體中沒(méi)有語(yǔ)句,一對(duì)大括號(hào)也是必不可少的。
4.4.4 消息傳遞
一個(gè)對(duì)象和外部交換信息主要靠方法的參數(shù)來(lái)傳遞,如果允許的話,外部對(duì)象也可以直接存取一個(gè)對(duì)象的成員變量。
在Java中調(diào)用方法時(shí),如果傳遞的參數(shù)是基本數(shù)據(jù)類型,在方法中將不能改變參數(shù)的值,你只能使用它們。如果傳遞的是對(duì)象引用,你也不能在方法中修改這個(gè)引用,但可以調(diào)用對(duì)象的方法以及修改允許存取的成員變量。所以想改變參數(shù)的值,可采用傳遞對(duì)象的方法,間接修改參數(shù)的值。
例1:class SC{
public static void main(String[] args){
int m=10, n=20 ;
Power p=new Power( ) ;
p.doPower(m , n);
System.out.println("x="+m+",y="+n);
System.out.println("x="+p.x+",y="+p.y) ; } }
class Power{
int x , y ;
void doPower(int a , int b)
{ x=a*a ;
y=b*b ; } }
運(yùn)行結(jié)果:x=10,y=20
x=100,y=400
例2:class SC{
float ptValue ; //成員變量
public static void main(String[] args){
int val=11 ; // 局部變量
SC pt=new SC( ) ;
System.out.println("val1="+val) ;
pt.changeInt(val) ;
System.out.println("val2="+val) ;
pt.ptValue=101f ; //float類型,加f
System.out.println("valValue1="+pt.ptValue) ;
pt.ChangeObj(pt) ;
System.out.println("valValue2="+pt.ptValue) ; }
public void changeInt(int value) //參數(shù)是簡(jiǎn)單類型
{value=55 ; }
public void ChangeObj(SC ref)//參數(shù)是對(duì)象引用類型
{ref.ptValue=99f ; }
}
運(yùn)行結(jié)果:val1=11
val2=11
valValue1=101.0
valValue2=99.0
作業(yè):P87-16 class Rectangle {
double width,height;
double zc(double b1,double b2)
{ return 2*(b1+b2); }
double mj(double b1,double b2)
{ return b1*b2; }}
public class SC{
public static void main(String args[]){
Rectangle r=new Rectangle();
r.width=10 ; r.height=20;
System.out.println("周長(zhǎng)="+r.zc(r.width,r.height)) ;
System.out.println("面積="+r.mj(r.width,r.height)) ; }}
作業(yè):P87-17 public class SC{
public static void main(String args[]) {
int m[]={1,2,3,4,5};
Array A=new Array(m);
A.sum( );
System.out.println(A.getsum()); }}
class Array{
private int n[];
int sum=0;
Array(int i[]) { n=i; }
void sum( ){
for (int x=0;x<n.length;x++)
sum=sum+n[x] ; }
int getsum( ){
return sum; } }