形式參數,是在方法定義階段,是定義某個函數時使用的參數,用於接收實參傳入。例f(x,y)中x和y是形參。java
實際參數,是在方法調用階段,是主調函數調用有參函數時,實際傳遞的內容。例f(3,7)中3和7是實參。app
值傳遞和引用傳遞不是簡單地經過傳遞內容區分的。若是是值,就是值傳遞;若是是引用,就是引用傳遞。這一理解是不正確的。函數
值傳遞,是指在調用函數時將實際參數複製一份傳遞給函數形參。此時,在函數中對形參作修改,不影響實際參數。ui
引用傳遞,是指在調用函數時將實際參數的地址直接傳遞給函數形參。此時,在函數中對參數作修改,將影響實際參數。code
根本區別在於值傳遞會建立副本,所以函數中沒法改變原始對象;引用傳遞不建立副本,函數中能夠改變原始對象。對象
public class ParamPassing { private static int intStatic = 222; private static String stringStatic = "old string"; private static StringBuilder stringBuilderStatic = new StringBuilder("old stringBuilder"); public static void main(String[] args) { // 方法調用1 method(intStatic); System.out.println(intStatic); // 方法調用2 method(); System.out.println(intStatic); // 方法調用3 method(stringStatic); System.out.println(stringStatic); // 方法調用4 method(stringBuilderStatic, stringBuilderStatic); System.out.println(stringBuilderStatic); } // 方法1 public static void method(int intStatic) { intStatic = 777; } // 方法2 public static void method() { intStatic = 888; } // 方法3 public static void method(String stringStatic) { stringStatic = "new string"; } // 方法4 public static void method(StringBuilder stringBuilderStatic1, StringBuilder stringBuilderStatic2) { stringBuilderStatic1.append(".method.first-"); stringBuilderStatic2.append(".method.second-"); // 引用從新賦值 stringBuilderStatic1 = new StringBuilder("new stringBuilder"); stringBuilderStatic1.append("new method's append"); } } 運行結果: 222 888 old string old stringBuilder.method.first-.method.second-
方法1,參數是局部變量,拷貝的變量值是777,會存入虛擬機棧中的局部變量表的第一個位置。在方法內部,根據做用於就近原則,使用局部變量的參數,操做與實參無關。而方法2,先把本地賦值的888壓入虛擬機棧中的操做棧,而後給靜態遍歷intStatic賦值。blog
方法3,String是immutable對象,類中沒有提供任何方法用來修改對象。「old string"仍然由實參持有,在方法3中,會從新new一個String對象,並把引用賦給形參。圖片
方法4,直接使用參數引用,能夠修改對象;當對引用從新賦值後,再也不影響實參。
當stringBuilderStatic引用做爲實參傳遞給形參stringBuilderStatic1時,此時形參是stringBuilderStatic的一個副本,兩個引用共同指向StringBuilder對象所在的堆內存地址,此時對形參的任何修改都會改變對象屬性。當建立新對象並賦值給stringBuilderStatic1後,該引用指向了新的內存地址,對其修改不會改變原對象的屬性。內存
字節碼解釋ci
0: aload_0 // 引用類型入棧 1: ldc #14 // 將常量值從常量池推到棧頂 // String .method.first- 3: invokevirtual #15 // 調用實例方法 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 6: pop // 棧頂元素出棧
14: new #17 // 建立實例 // class java/lang/StringBuilder 17: dup // 賦值棧頂數值,壓入棧頂 18: ldc #18 // String new stringBuilder 20: invokespecial #19 // 實例初始化 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 23: astore_0 // 將棧中ref引用存到局部變量表 24: aload_0 // 加載局部變量到操做數棧 25: ldc #20 // 加載常量到操做數棧 // String new method's append 27: invokevirtual #15 // 調實例方法 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 30: pop // 操做數棧頂元素出棧 31: return // 方法返回指令