- Java語言GUI程序設計
- 趙滿來
- 5044字
- 2019-12-06 14:22:13
4.1 類的方法
如2.3節所述,方法是類定義的主要組成部分,是對類中域變量進行操作的程序單元。Java語言的方法必須在類中,不能有位于類之外的方法。
4.1.1 方法的定義
Java語言中方法定義的一般格式是:
[修飾符] 返回值類型 方法名(類型 參數名1, 類型 參數名2, …) { // 這對大括號內是方法體 一些變量聲明語句 一些執行語句 return 表達式; }
其中,修飾符是可選的,可以限定該方法的可見范圍或其他特性,隨后介紹。
(1)返回值類型:方法完成對數據的計算和處理等操作之后獲得了處理結果,可能需要將結果返回給請求這個方法的對象,返回值類型告訴該方法會返回什么類型的數據。方法的具體返回值就是return語句后表達式的值。如果沒有返回數據,則用void關鍵字說明,此時return語句后沒有表達式部分,或者干脆不要return語句。例如,前面例題中自動生成的事件處理方法(如addNumber)就沒有返回值,其返回值類型為void,方法體中沒有return語句。
(2)方法名:為該方法取的在該類中的唯一名字,符合Java標識符規則。對象等通過方法名請求該方法。一般方法名的第一個字母小寫。
(3)參數表:在方法名后的一對小括號內定義,聲明了每個參數的類型和參數名。如果有多個參數,使用逗號“,”分隔。
從Java 5開始還可以在方法參數表中定義一個可變元參數,即參數個數不確定而參數類型確定的參數表。可變元參數必須在整個參數表的最后,形式是:類型…參數名。例如:
int calcAvg(float avg, int...values) { // … return avg; }
(4)變量聲明:方法體中聲明的變量一般是計算過程中使用的一些中間變量,它的使用范圍是在該方法體內,出了這個方法的最后一個大括號“}”,這些變量就不能使用了,因此叫作局部變量。
事實上,在任何一個語句塊內定義的變量都是局部變量,出了這個語句塊范圍就不能使用。局部變量必須在使用之前初始化,如果沒有賦初值則不能獲得一個默認值,而是保存有一個隨機值。
Java 10中可以采用“var變量名=初值;”的方式定義局部變量,Java 10會根據初值的類型推斷此變量的類型,此后在其作用域范圍內會保持其類型。例如,語句“var x=10;”則使變量x為int類型,此后若執行語句“x=10.1;”會發生類型不兼容錯誤。應注意,在定義字段變量,方法的參數及方法返回值的類型時,不能使用保留字var。
(5)執行語句:方法體中的執行語句對類的域變量、方法體中的局部變量及參數變量進行操作,可以是賦值語句、流程控制語句以及調用其他方法的語句等。方法體內可以直接使用它本身定義的局部變量、該方法的參數變量以及方法所在類中的域變量。
例如,例3.4四則運算計算器程序中“=”按鈕的鼠標單擊事件處理方法(見圖4.1),方法名是calcOpr;void表示該方法無返回值;參數表中只有一個參數——參數類型是java.awt.event.ActionEvent類,參數名是evt;118行稱為方法頭。該方法體中定義了6個局部變量,strNum1、strNum2和opr是String類型,num1、num2和result是int類型;其中,strNum1和strNum2的作用范圍是整個calcOpr方法,其余4個局部變量作用范圍是122~143行的if語句塊;使用if、if-else-if語句、賦值語句、jTextFieldResult對象的setText和getText等方法調用以及jComboBoxOpr對象的getSelectedItem方法調用等執行語句根據用戶選擇的運算種類獲得運算結果,并將結果使用文本字段組件顯示出來。

圖4.1 例3.4程序“=”按鈕事件處理方法
4.1.2 方法的調用及參數傳遞
對類的對象中方法的執行請求就是對該方法的調用。請求執行方法的對象是調用者,而被請求執行的方法是被調用方法。例如,在book.ifdemos.ArithmeticClac類的calcOpr方法中調用了jTextFieldNum1對象的getText方法(見圖4.1第120行語句),方法調用者就是calcOpr方法所屬的對象;又如,chap03項目的ArithmeticClac.java文件中的以下程序段:

在第53行調用了calcOpr方法,方法調用者和被調用方法屬于同一個對象。
方法調用的一般形式是:
對象名.方法名(參數表);
(1)對象名:該對象名是被調用方法所屬的對象。例如,圖4.1第120行語句的對象名jTextFieldNum1指明調用的getText方法是第一個文本字段組件(對象)的方法,而不是第二個文本字段組件或顯示運算結果文本字段組件的getText方法。如果被調用方法與調用者是同一個對象,則可以省略方法名前面的對象名,例如上段代碼的第53行。
(2)參數表:此參數表是一些表達式、常量或變量組成的列表,每個參數都有一個確定值,與方法定義時的參數表所列的參數的類型、次序和個數一一對應,多個參數之間用逗號“,”分隔。方法定義時的參數稱為形式參數,簡稱形參,參數表也叫形參表;方法調用時給出的參數稱為實際參數,簡稱實參,參數表也叫實參表。例如,如圖4.1所示calcOpr方法定義的形參表只有一個形參evt,形參類型是java.awt.event.ActionEvent類,上段代碼第53行調用calcOpr方法時給出的實參是變量evt,evt是第52行聲明的java.awt.event.ActionEvent類的對象。
在調用具有可變元參數的方法時,實參也要與形參對應。例如,前面定義的方法calcAvg,調用時第一個實參必須是float類型的,后面是多個int類型的實參,如“calcAvg(3.2f, 3, 5, 10, 40);”是正確的,但是“calcAvg(3.2f, 3, 5, 10.0, 40);”則是錯誤的,因為第4個實參類型并不是int。
Java程序中方法的調用是按值調用,即調用者將實參的值傳遞給被調方法對應的形參。如果方法的參數是基本數據類型,則實參向形參傳值的過程十分直觀,就是形參復制了實參的值,在方法中對形參的改變不會影響實參。
例4.1 編寫方法swap交換兩個int型變量的值,并顯示交換前后形參和實參的值。
解:按照以下步驟操作。
(1)在NetBeans IDE中創建一個Java應用程序項目,項目名稱為chap04。
(2)創建包book.methoddemos,并在該包中新建JFrame窗體,類名為VarSwap。
(3)設計如圖4.2所示的界面,其中,文本字段組件jTextFieldVar1和jTextFieldVar2分別用于輸入兩個整數,jTextFieldVar1A和jTextFieldVar2A分別顯示調用交換方法swap后實參的值,jTextFieldArg1和jTextFieldArg2分別顯示調用交換方法swap前形參的值,jTextFieldArg1A和jTextFieldArg2A分別顯示調用交換方法swap后形參的值。這8個文本字段組件的columns屬性值設置為8,除jTextFieldVar1和jTextFieldVar2之外的其他6個editable屬性值都設置為false。其余組件按照圖4.2導航器窗口中內容命名。

圖4.2 例4.1程序界面設計視圖
(4)在VarSwap類中設計方法swap,源代碼如下。

(5)為“交換”按鈕jButtonSwap組件添加actionPerformed事件處理方法swapVars,該方法源代碼如下。

(6)為“清除”按鈕jButtonClear組件添加actionPerformed事件處理方法clearAll,該方法源代碼如下。
private void clearAll(java.awt.event.ActionEvent evt) { // TODO add your handling code here: jTextFieldVar1.setText(""); jTextFieldVar2.setText(""); jTextFieldVar1A.setText(""); jTextFieldVar2A.setText(""); jTextFieldArg1.setText(""); jTextFieldArg2.setText(""); jTextFieldArg1A.setText(""); jTextFieldArg2A.setText(""); }
完成上述步驟后運行程序,在var1和var2右邊的文本框中輸入兩個整數后單擊“交換”按鈕,發現兩個實參變量在調用交換方法swap后仍然保持原值不變,而兩個形參的值則在執行交換操作后確實進行了交換(見圖4.3)。

圖4.3 整數類型實參不受調用方法的影響
如果方法調用所傳遞的參數是引用類型的變量,則將實參的引用值復制給形參的引用變量。此時,相對應的實參和形參鏈接到同一個對象,在方法中改變了形參引用對象時,其實就是改變了實參引用的對象。
例4.2 TwoInt類中有兩個int類型的屬性,編寫方法swap交換該類對象的兩個屬性的值,并顯示交換前后形參引用對象和實參引用對象的屬性值。
解:按照以下步驟操作。
(1)右擊book.methoddemos包中VarSwap.java文件名,在快捷菜單中單擊“復制”菜單項。右擊book.methoddemos包名,在快捷菜單中單擊“粘貼”|“重構復制”菜單項,新名稱輸入“ObjSwap”,單擊“重構”按鈕。
(2)將“var 1:”“var2:”“arg 1:”“arg2:”標簽上的文字(text屬性)修改為“var.var1:”“var.var2:”“var.arg1:”“var.arg2:”。
(3)右擊book.methoddemos包名,在快捷菜單中單擊“新建”|“Java類”菜單項,類名輸入“TwoInt”,單擊“完成”按鈕。
(4)在TwoInt類中添加兩個整型域,完成后該類的源代碼如下(空行和注釋部分省略)。
package book.methoddemos; public class TwoInt { int var1; int var2; }
(5)修改ObjSwap類中的swap方法。完成修改后該方法的源代碼如下。
void swap(TwoInt arg) { // 顯示交換前形參的值 jTextFieldArg1.setText(arg.var1+""); jTextFieldArg2.setText(arg.var2+""); // 執行交換 int t = arg.var1; arg.var1 = arg.var2; arg.var2 = t ; // 顯示交換后形參的值 jTextFieldArg1A.setText(arg.var1+""); jTextFieldArg2A.setText(arg.var2+""); }
(6)修改ObjSwap類中的swapVars方法。完成修改后該方法的源代碼如下。

完成上述步驟后運行ObjSwap.java文件,在var.var1和var.var2右邊的文本框中輸入兩個整數后單擊“交換”按鈕,發現實參變量所引用的對象在調用交換方法swap后發生改變——對象的兩個屬性值發生了交換,形參所引用的對象在執行交換操作后兩個屬性值也進行了交換(見圖4.4)。

圖4.4 例4.2程序運行結果——參數引用的對象發生改變
如果例4.1中的swap方法修改為swap(javax.swing.JTextField arg1, javax.swing.JTextField arg2),在事件處理方法swapVars中調用swap(jTextFieldVar1, jTextFieldVar2),即傳遞接收用戶輸入的兩個文本字段組件的引用,則arg1也鏈接到第一個文本字段組件,arg2鏈接到第二個文本字段組件。在swap方法體內交換arg1和arg2的值,那么只是arg1鏈接到第二個文本字段組件,arg2鏈接到第一個文本字段組件,實參變量jTextFieldVar1仍然鏈接到第一個文本字段組件,jTextFieldVar2仍然鏈接到第二個文本字段組件。顯然,在被調方法中無法改變調用者實參引用。要在被調方法中改變實參引用對象的狀態,可以將該對象引用傳遞給形參,使形參也鏈接到這個對象,之后就可以通過形參引用修改該對象的狀態。
4.1.3 方法的重載
在例4.1和例4.2中看到了兩個同名方法swap,其作用都是交換兩個變量的值,但是由于是在兩個不同的類中,有不同的作用范圍,因此方法名字相同并沒有什么不妥。有時候會遇到在同一個類中作用相同的兩個或多個方法的情形,如果它們也可以使用相同的方法名,則可以減輕該類的使用者的記憶負擔。例如,需要設計方法實施兩個數相加,但是這兩個數可能是整數,也可能是浮點數,甚至是兩個byte類型數;又如,還需要設計方法實施兩個數、三個數、四個數相加。為此,Java語言提供了方法重載機制,可以定義多個具有相同方法名但參數表不同的方法——可以是參數個數相同但類型不同,也可以是參數個數不同。重載的方法應該有相同的返回值類型。
1. 參數個數相同類型不同的重載方法
例如,String類中以下valueOf方法分別使用不同類型的一個參數,而形成方法重載。
public static String valueOf(boolean b):返回boolean參數的字符串表示形式。
public static String valueOf(char c):返回char參數的字符串表示形式。
public static String valueOf(int i):返回int參數的字符串表示形式。
public static String valueOf(long l):返回long參數的字符串表示形式。
public static String valueOf(float f):返回float參數的字符串表示形式。
public static String valueOf(double d):返回double參數的字符串表示形式。
又如,String類中以下兩個indexOf方法參數個數相同,但第一個參數類型不同,而第二個參數類型相同,從而形成方法重載。
indexOf(int ch, int fromIndex):返回在該字符串中指定字符ch第一次出現處的索引,從指定的索引fromIndex開始搜索。
indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出現處的索引,從指定的索引開始。
再如,以下OverloadDemo1類中的三個addNums方法都有兩個參數,但參數類型不同從而形成重載。

2. 參數個數不同的重載方法
例如,String類中以下substring方法是參數個數不同的兩個重載方法。
public String substring(int beginIndex)返回一個新的字符串,它是此字符串的一個子字符串。該子字符串從指定索引beginIndex處的字符開始,直到此字符串末尾。
public String substring(int beginIndex, int endIndex)返回一個新字符串,它是此字符串的一個子字符串。該子字符串是從指定的beginIndex處開始,直到索引endIndex ? 1處的字符序列。因此,該子字符串的長度為endIndex?beginIndex。
再如,在OverloadDemo1類中設計以下兩個方法可以查找計算2~n和m~n自然數中的素數。其中,第一個方法只需給出結束的那個自然數,而第二個方法則需要給出起始和結束的兩個自然數,由于方法參數個數不同而方法名相同構成重載。

4.1.4 構造方法
類的對象中包含域變量,創建了對象就需要對它的域變量進行初始化,盡管沒有明確初始化的域變量會有默認初值,但是大部分情況下默認初值是不能滿足需求的。Java語言允許且鼓勵為類定義構造方法以實現對類對象的初始化。
構造方法與一般方法的結構一樣,但構造方法名與類名相同,不能有返回值,也無返回值類型聲明,參數表可以為空或定義多個參數。根據需要可以為一個類定義多個重載的構造方法。在創建類的對象時自動調用它的構造方法,跟在new操作符之后的就是相應構造方法的調用形式——給出對應的實參表。
例4.3 為例2.7完成的用戶登錄程序界面(見圖2.58)編寫用戶信息類,其中,用戶信息包括用戶名、密碼和用戶身份三個方面的內容。
解:按照以下步驟操作。
(1)右擊book.methoddemos包名,在快捷菜單中單擊“新建”|“Java類”菜單項,類名輸入“User”,單擊“完成”按鈕。
(2)在生成的User類體中添加三個域變量,輸入以下代碼。
String name; String password; int job;
(3)單擊主菜單中的“源”|“插入代碼”|“構造函數”菜單項,在“生成構造函數”對話框中單擊“全選”按鈕,然后單擊“生成”按鈕(見圖4.5)。
(4)在“源”代碼編輯窗口右擊,在快捷菜單中單擊“插入代碼”|“getter和setter”菜單項,在“生成getter和setter”對話框中單擊“全選”按鈕,單擊“封裝字段”前面的復選框選取該項,然后單擊“生成”按鈕(見圖4.6)。

圖4.5 “生成構造函數”對話框

圖4.6 “生成getter和setter”對話框
(5)在“源”代碼編輯窗口右擊,在快捷菜單中單擊“插入代碼”|“equals ()和hashCode()”菜單項,在“生成equals ()和hashCode()”對話框中單擊兩個“全選”按鈕,然后單擊“生成”按鈕(見圖4.7)。

圖4.7 “生成equals ()和hashCode()”對話框
(6)單擊主菜單中的“源”|“插入代碼”|“構造函數”菜單項,在“生成構造函數”對話框中單擊name : String前面的復選框選擇該項,然后單擊“生成”按鈕。
完成上述操作步驟后即生成了User類的代碼。該類的源代碼如程序清單4.1所示(省略空行和注釋),可以看到有兩個重載的構造方法。
程序清單4.1:


- JBoss Weld CDI for Java Platform
- 深入理解Bootstrap
- PHP 7底層設計與源碼實現
- MySQL數據庫基礎實例教程(微課版)
- Python程序設計與算法基礎教程(第2版)(微課版)
- Buildbox 2.x Game Development
- 寫給大家看的Midjourney設計書
- 計算機組裝與維護(第二版)
- 零基礎學Java第2版
- 程序員的英語
- HTML5+CSS3+jQuery Mobile+Bootstrap開發APP從入門到精通(視頻教學版)
- JavaScript Mobile Application Development
- TensorFlow.NET實戰
- C語言解惑:指針、數組、函數和多文件編程
- React Native -Building Mobile Apps with JavaScript