一.聲明類
??你已經(jīng)見過了以如下方式定義的類:
classMyClass{// field, constructor, and method declarations}
??上面是聲明類的最基本的語法。可以在聲明類時(shí)提供更多的信息,例如它繼承的父類,或?qū)崿F(xiàn)的接口等,例如:
classMyClassextendsMySuperClassimplementsMyInterface{// field, constructor, and method declarations}
這意味著MyClass類繼承自MySuperClass類并是實(shí)現(xiàn)了MyInterface接口。
還可以在開頭加上修飾符,例如public、private、final等。有關(guān)這些修飾符的作用將在下文中進(jìn)行詳細(xì)的介紹。一般來說,類聲明由以下幾部分組成:
修飾符。例如public、private以及其他將會(huì)在后面見到的修飾符;
類名。按照慣例使用首字母大寫的駝峰命名法。
繼承的父類。使用關(guān)鍵字extend聲明,一個(gè)類只能直接繼承一個(gè)父類。
一個(gè)或多個(gè)實(shí)現(xiàn)的接口。使用關(guān)鍵字implements聲明,多個(gè)接口之間使用逗號(hào)隔開。
類體。定義在一對(duì)大括號(hào)中。
二.域的聲明
??Bicycle類使用以下幾行代碼聲明它的域:
publicintcadence;publicintgear;publicintspeed;
??域的聲明由以下幾部分組成:
修飾符,例如private、public、static、final等;
域的類型;
域的名稱。
權(quán)限修飾符
??權(quán)限修飾符用來控制其他類對(duì)一個(gè)成員的訪問權(quán)限。現(xiàn)在我們只討論public和private,其他權(quán)限修飾符將在后面的文章中介紹。
public:可以從所有類訪問該字段;
private:只能在自己的類中訪問。
??本著封裝的精神,應(yīng)該盡可能地將域的訪問權(quán)限設(shè)為private,這意味這只能在自己的類中訪問它的值。但是,其他類仍有訪問它的需要,可以通過添加訪問域的方法來供其他類訪問,就像下面這樣:
publicclassBicycle{privateintcadence;privateintgear;privateintspeed;publicBicycle(intstartCadence,intstartSpeed,intstartGear){? ? ? ? gear = startGear;? ? ? ? cadence = startCadence;? ? ? ? speed = startSpeed;? ? }publicintgetCadence(){returncadence;? ? }publicvoidsetCadence(intnewValue){? ? ? ? cadence = newValue;? ? }publicintgetGear(){returngear;? ? }publicvoidsetGear(intnewValue){? ? ? ? gear = newValue;? ? }publicintgetSpeed(){returnspeed;? ? }publicvoidapplyBrake(intdecrement){? ? ? ? speed -= decrement;? ? }publicvoidspeedUp(intincrement){? ? ? ? speed += increment;? ? }}
三.定義方法
??下面定義了一個(gè)方法:
publicintadd(inta,intb){returna + b;}
??方法定義中必需的是返回值類型,方法名,一對(duì)小括號(hào),以及大括號(hào)和方法體。更一般地來說,方法的聲明由六個(gè)部分組成:
修飾符——例如public、private、static等;
返回值類型——方法返回的數(shù)據(jù)的類型。若方法無返回值則為void;
方法名稱——和變量的命名規(guī)則相同,但慣例有一點(diǎn)不同;
參數(shù)列表——位于小括號(hào)中,用逗號(hào)隔開。方法也可以沒有參數(shù);
方法拋出的異?!嘘P(guān)這部分的內(nèi)容將在后續(xù)教程中進(jìn)行介紹;
方法體——位于大括號(hào)中,方法的具體代碼。
簽名:方法的簽名由方法名稱和參數(shù)列表組成。簽名用來在一個(gè)類中唯一地標(biāo)識(shí)一個(gè)方法,也就是說,一個(gè)類中不能存在兩個(gè)簽名相同的方法。上面的add方法的簽名為add(int a, int b)。
??方法的名稱可以是任何合法的標(biāo)識(shí)符。但是按照慣例,方法名的第一個(gè)單詞應(yīng)該是動(dòng)詞并且小寫它的首字母。例如run、compareTo等。
方法的重載
重載是指一個(gè)類中的兩個(gè)或多個(gè)方法具有相同的名稱但具有不同的參數(shù)列表。Java支持方法的重載,并且可以通過方法的簽名區(qū)分它們。
假設(shè)有一個(gè)計(jì)算器類Calculator。為不同類型的操作數(shù)的加法設(shè)計(jì)不同的名字是一件很麻煩的事,例如addInt、addDouble、addFloat等。在Java中,可以為這些方法使用相同的名稱,只要它們的參數(shù)列表是不同的。例如:
publicclassCalculator{publicstaticadd(inta,intb){returna + b;}publicstaticadd(doublea,doubleb){returna + b;}? ? ...}
??不能聲明名稱和參數(shù)列表都相同的方法,因?yàn)榫幾g器無法區(qū)分它們。編譯器在區(qū)分方法時(shí)只考慮簽名,所以名稱和參數(shù)列表相同,但返回值不同的兩個(gè)方法并不算重載,編譯器將會(huì)給出錯(cuò)誤。
四.構(gòu)造器
??構(gòu)造器(也稱構(gòu)造方法)是將類實(shí)例化為對(duì)象是自動(dòng)調(diào)用的方法。但與普通方法不同的是,它的名字與類名相同且沒有返回值。例如,Bicycle類有一個(gè)構(gòu)造方法:
publicBicycle(intstartCadence,intstartSpeed,intstartGear){? ? gear = startGear;? ? cadence = startCadence;? ? speed = startSpeed;}
??在創(chuàng)建對(duì)象時(shí),new運(yùn)算符將會(huì)調(diào)用構(gòu)造方法:
Bicycle myBike =newBicycle(30,0,8);
??一個(gè)類可以有多個(gè)構(gòu)造方法,只要它們的參數(shù)列表不同。還可以有無參構(gòu)造方法:
publicBicycle(){? ? gear =1;? ? cadence =10;? ? speed =0;}
如果沒有提供構(gòu)造方法,編譯器將會(huì)自動(dòng)提供一個(gè)無參構(gòu)造方法,這個(gè)無參構(gòu)造方法會(huì)自動(dòng)調(diào)用父類的無參構(gòu)造方法。如果父類沒有無參構(gòu)造方法,編譯器將會(huì)給出錯(cuò)誤。因此在不提供構(gòu)造方法時(shí)要保證父類有無參構(gòu)造方法。如果你的類沒有明確的父類,那么它有一個(gè)隱含的父類Object,這個(gè)類有一個(gè)無參構(gòu)造方法。
可以在構(gòu)造方法中手動(dòng)調(diào)用父類的構(gòu)造方法,有關(guān)這部分的內(nèi)容將會(huì)在接口和繼承的教程中介紹。還可以在構(gòu)造方法的聲明中使用訪問修飾符來控制哪些類可以調(diào)用構(gòu)造函數(shù)。如果某個(gè)類不能調(diào)用本類的構(gòu)造方法,則無法在該類內(nèi)部直接創(chuàng)建本類對(duì)象。
五.向方法或構(gòu)造器傳遞參數(shù)
??方法的參數(shù)分為形式參數(shù)和實(shí)際參數(shù)。形式參數(shù)(簡稱形參)是方法聲明中的參數(shù)列表,實(shí)際參數(shù)(簡稱實(shí)參)是指在調(diào)用方法時(shí)傳遞的具體的值。調(diào)用方法時(shí),實(shí)際參數(shù)的順序和類型必須與形式參數(shù)完全匹配。例如之前定義的add方法:
intadd(inta,intb){returna + b;}
??下面的語句調(diào)用了這個(gè)方法并把返回值賦值給變量sum,2和3就是調(diào)用方法時(shí)傳遞的實(shí)參:
intsum = add(2,3);
??還可以傳遞任意數(shù)量的參數(shù)。例如讓add方法可以計(jì)算任意數(shù)量的整數(shù)的和:
intadd(int... a){intsum =0;for(inti =0; i < a.length; i++) {? ? ? ? sum += a[i];? ? }returnsum;}
可以看到,在方法內(nèi)部,這個(gè)參數(shù)被視為一個(gè)數(shù)組,可以通過數(shù)組的訪問形式去訪問每一個(gè)參數(shù)。需要注意的是,參數(shù)列表中只能有一個(gè)這樣的參數(shù),并且它必須放在最后一個(gè)位置上。
形參的名稱如果與類的某個(gè)域的名稱相同,那么在這個(gè)方法內(nèi),這個(gè)形參將會(huì)屏蔽與它同名的域。可以使用this關(guān)鍵字來區(qū)分同名的形參和域,有關(guān)this關(guān)鍵字的內(nèi)容將會(huì)在后面的文章中討論。
基本數(shù)據(jù)類型參數(shù)
??基本數(shù)據(jù)類型的參數(shù)按值傳遞到方法中。這意味著對(duì)參數(shù)值的任何更改都僅存在于方法的范圍內(nèi)。方法返回時(shí),參數(shù)消失,對(duì)它們的任何更改都將丟失。下面是一個(gè)例子:
publicclassPassPrimitiveByValue{publicstaticvoidmain(String[] args){inta =1;? ? ? ? increment(a);? ? ? ? System.out.println(a);? ? }publicstaticvoidincrement(intx){? ? ? ? x = x +1;? ? }}
??這個(gè)程序會(huì)輸出1而不是2。x只是接收了a的值,對(duì)x的操作與a完全沒有關(guān)系,所以函數(shù)結(jié)束后,a的值還是1。
引用類型參數(shù)
??引用類型的參數(shù)將引用傳遞到方法中。對(duì)形參的操作就相當(dāng)于對(duì)實(shí)參進(jìn)行同樣的操作。例如:
publicclassPassPrimitiveByReference{publicstaticvoidmain(String[] args){? ? ? ? Foo foo =newFoo(1);? ? ? ? changeBar(foo);? ? ? ? System.out.println(foo.getBar());? ? }publicstaticvoidchangeBar(Foo f){? ? ? ? f.setBar(2);? ? }}classFoo{privateintbar;publicFoo(intbar){this.bar = bar;}publicintgetBar(){returnbar;}publicvoidsetBar(intbar){this.bar = bar;}}
??這個(gè)程序會(huì)輸出2。因?yàn)樾螀和實(shí)參foo引用了同一個(gè)對(duì)象。