方法的形參和實參
在Java中,方法的形參(Formal Parameter)和實參(Actual Parameter)是呼叫方法時引數傳遞的兩個關鍵概念。
形參(Formal Parameter)
- 定義:形參是在方法宣告中指定的引數,用於接收呼叫方法時傳遞的值。形參相當於是方法內部的區域性變數。
- 作用:形參為方法提供了一個或多個輸入的佔位符,允許方法接收外部資料。
- 特點:
- 形參的型別和數量必須與呼叫方法時提供的實參匹配。
- 形參僅在方法被呼叫時存在,呼叫結束後,形參所佔用的記憶體會被釋放。
實參(Actual Parameter)
- 定義:實參是在呼叫方法時實際傳遞給方法的值或變數。
- 作用:實參用於初始化形參,將資料傳遞給方法。
- 特點:
- 實參可以是常量、變數、表示式或任何可以求值的結果。
- 實參的個數和型別必須與方法定義中的形參列表一致。
- 實參的求值順序對方法呼叫的結果沒有影響,因為引數是透過值傳遞的。
呼叫方法時的引數傳遞
當呼叫一個方法時,實參的值會被複制到形參中。這個過程稱為“按值傳遞”(Pass by Value)。這意味著:
- 如果實參是一個基本資料型別(如int、double等),則傳遞的是實際的值。
- 如果實參是一個物件引用,傳遞的是引用的副本,但副本指向同一個物件。
示例
public class Example {
// 方法宣告,包含兩個形參
public void printInfo(int id, String name) {
System.out.println("ID: " + id + ", Name: " + name);
}
public static void main(String[] args) {
Example ex = new Example();
// 呼叫方法,傳遞實參
int studentId = 1;
String studentName = "John Doe";
ex.printInfo(studentId, studentName);
}
}
在這個例子中:
-
printInfo
方法有兩個形參:int id
和String name
。 -
在
main
方法中,我們建立了兩個變數studentId
和studentName
作為實參。 -
當呼叫
ex.printInfo(studentId, studentName);
時,studentId
和studentName
的值被複制到printInfo
方法的形參中。 -
形參是方法定義的一部分,用於接收呼叫時傳遞的資料。
-
實參是呼叫方法時實際傳遞的資料。
-
Java方法呼叫是按值傳遞的,這意味著基本資料型別的值會被複制,而物件引用的副本會指向同一個物件。
在Java中,方法引數的傳遞機制通常被稱為“值傳遞”,但這個術語可能會引起一些混淆,因為它與“引用傳遞”的概念有關。為了澄清這一點,讓我們詳細解釋這兩個概念:
值傳遞(Pass by Value)
- 定義:在Java中,所有方法呼叫都是透過值傳遞的。這意味著當一個方法被呼叫時,實際上傳遞的是引數值的複製。
- 作用:值傳遞確保了方法內部對引數的修改不會影響到原始的引數值。
- 特點:
- 對於基本資料型別(如
int
、double
、char
等),當方法被呼叫時,會建立一個新的數值副本,方法內部對這些數值的操作不會影響原始變數。- 對於物件引用,傳遞的是引用的副本,但這個副本指向同一個物件。因此,如果方法內部修改了物件的內部狀態(即物件的欄位),這些修改將反映在原始物件上。但如果方法內部嘗試重新分配引用(即讓副本指向一個新的物件),這不會改變原始引用。
引用傳遞(Pass by Reference)
概念誤解:在Java中,沒有真正的“引用傳遞”。儘管有時會這樣描述,但實際上Java總是透過值傳遞引數。
作用:當傳遞的是物件引用時,方法可以操作物件的狀態,因為所有引用副本都指向同一個物件。
特點:
儘管傳遞的是引用的副本,但副本和原始引用都指向堆記憶體中的同一個物件。因此,對物件屬性的任何修改都會影響到原始物件。
如果嘗試在方法內部重新分配引用(例如,將引數引用指向一個新的物件),這不會影響原始引用,因為只有副本被修改了。
註釋:引用傳遞事實上只是複製了實參的地址
示例
public class Test { public static void main(String[] args) { int num = 5; // 基本資料型別 String str = "Hello"; // 物件引用 changeInt(num); // 呼叫方法,傳遞基本資料型別的值 changeString(str); // 呼叫方法,傳遞物件引用的副本 } public static void changeInt(int n) { n = 10; // 修改副本,不影響原始變數 } public static void changeString(String s) { s = "World"; // 重新分配引用,不影響原始引用 s.toUpperCase(); // 修改物件狀態,影響原始物件 } }
在這個例子中:
changeInt
方法嘗試修改傳遞的整數,但由於是值傳遞,原始變數num
不受影響。changeString
方法首先嚐試重新分配引用s
,這不會影響原始引用str
。然後呼叫toUpperCase()
方法修改了字串物件的狀態,這影響了原始物件,因為所有引用(包括原始引用)都指向同一個物件。總結
- Java總是透過值傳遞引數,無論是基本資料型別還是物件引用。
- 對於基本資料型別,方法內部的修改不會影響到原始變數。
- 對於物件引用,方法可以修改物件的狀態,但重新分配引用隻影響副本,不影響原始引用。