国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

深入解析Java編程中方法的參數傳遞

2019-11-26 14:54:26
字體:
來源:轉載
供稿:網友

在閱讀本文之前,根據自己的經驗和理解,大家可以先思考并選擇一下Java函數的參數傳遞方式:
A. 是按值傳遞的?
B. 按引用傳遞的?
C. 部分按值部分按引用?
此處暫不宣布正確答案,我們通過一個簡單的例子讓大家自己找答案:
1. 先定義一個類型Value

public static class Value {   private String value = "value";   public String getValue() { return value; }   public void setValue(String value) { this.value = value; } } 

2. 寫兩個函數newValue和modifyValue:newValue會將入參指向一個新的對象,modifyValue會調用入參的setValue方法修改對象的value值。

public static void newValue(Value value) {   value = new Value();   value.setValue("new value");   System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); }    public static void modifyValue(Value value) {   value.setValue("new value");   System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue()); } 

3. 簡單的測試代碼

public static void main(String[] args) {   Value value1 = new Value();   System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue());   // 將value1指向新的Value對象   newValue(value1);   System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "/n");   Value value2 = new Value();   System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());   // 使用object的set方法,修改對象的內部值   modifyValue(value2);   System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue()); } 

4. 執行結果日志:

Before modify, HashCode = 12677476, value = value In newValue, HashCode = 33263331, value = new value After modify, HashCode = 12677476, value = value  Before modify, HashCode = 6413875, value = value In modifyValue, HashCode = 6413875, value = new value After modify, HashCode = 6413875, value = new value 


5. 結果分析:
上述代碼這是非常常見的一種編程模式:在外圍定義|保存|獲取一個值或對象,將這個對象作為參數傳入一個方法,在方法中修改對象的屬性、行為。但兩個方法newValue和modifyValue的修改方式不一樣,在方法調用之后,該對象在外圍看來也有很大的差別!如何理解這種差異呢?先溫故一下按值傳遞、按引用傳遞的概念:
* 按值傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本。因此,如果函數修改了該參數,僅改變副本,而原始值保持不變。
* 按引用傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的內存地址,而不是值的副本。因此,如果函數修改了該參數,參數的原始值(函數塊之外的調用代碼中)也隨之改變。
正確的答案:A――Java函數是按值傳遞參數的!
分析一下日志:
* 第一段日志輸出,value1參數在newValue方法內部被改為指向新對象,并輸出了新對象的hashCode和value值,但跳出newValue方法域之后,在main方法中的value1沒有發生任何變化,這符合按值傳遞的定義和特點;如果是按引用傳遞,value1在調用newValue(Value value)方法之后,應該是發生變化的。
* 第二段日志輸出,value2在modifyValue方法內部進行了setValue操作,hashCode不變而value被修改,離開modifyValue方法域之后,在main方法中value2確實發生了變更。使用過C++的人容易將這種現象理解為:按引用傳遞函數參數!因為這跟C++中的按引用傳遞像極了!但這里恰恰是最容易陷入誤區的地方!
兩段日志的不同現象背后所隱藏的是原理是:Java語言是按值傳遞參數,按引用傳遞對象的;Java中所操作的對象其實都是操作對象的引用,object本身保存在“堆”中,而對象的“引用“保存在寄存器或“棧”中。
偽代碼描述一下newValue方法和modifyValue方法的不同之處:

newValue{   Value_ref2 = value_ref1;  // 按值傳入引用value_ref1,得到value_ref1的副本   value_obj2 = new Value();  // value_obj2被創建、初始化在“堆“中   value_ref2 -> value_obj2;  // value_ref2 指向value_obj2 value_ref2 ->value_obj2.setValue(“xxx”); // value_obj2 的value被修改 printValueObj2();      // 此處打印的是obj2的值 } modifyValue{   Value_ref2 = value_ref1;  // 按值傳入引用value_ref1,得到value_ref1的副本 value_ref2 ->value_obj1.setValue(“xxx”); // value_obj1 的value被修改 printValueObj1();      // 此處打印的是obj1的值 } 

夠清楚了吧!value1_ref1在作為參數傳入函數的時候,首先被復制了一份副本value1_ref2供函數域使用,此時這兩個ref都是指向同一個value_obj; newObject函數中的代碼[ value = new Value(); ] 其實是將value1_ref1指向了一個新的對象value_obj2;在這之后的set操作都是對新對象的操作;modifyValue函數是通過set方法直接操作value_obj1,這是跟newValue函數的不同之處。

通過值傳遞參數
調用一個方法時候需要提供參數,你必須按照參數列表指定的順序提供。
例如,下面的方法連續n次打印一個消息:

public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++)  System.out.println(message);}

示例
下面的例子演示按值傳遞的效果。
該程序創建一個方法,該方法用于交換兩個變量。

public class TestPassByValue {  public static void main(String[] args) {   int num1 = 1;   int num2 = 2;   System.out.println("Before swap method, num1 is " +             num1 + " and num2 is " + num2);   // 調用swap方法   swap(num1, num2);   System.out.println("After swap method, num1 is " +             num1 + " and num2 is " + num2);  }  /** 交換兩個變量的方法 */  public static void swap(int n1, int n2) {   System.out.println("/tInside the swap method");   System.out.println("/t/tBefore swapping n1 is " + n1              + " n2 is " + n2);   // 交換 n1 與 n2的值   int temp = n1;   n1 = n2;   n2 = temp;   System.out.println("/t/tAfter swapping n1 is " + n1              + " n2 is " + n2);  }}

以上實例編譯運行結果如下:

Before swap method, num1 is 1 and num2 is 2    Inside the swap method        Before swapping n1 is 1 n2 is 2        After swapping n1 is 2 n2 is 1After swap method, num1 is 1 and num2 is 2

傳遞兩個參數調用swap方法。有趣的是,方法被調用后,實參的值并沒有改變。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阿克陶县| 江永县| 龙里县| 安龙县| 盱眙县| 五台县| 安远县| 普宁市| 东莞市| 启东市| 丹棱县| 锡林浩特市| 武鸣县| 扎囊县| 海林市| 小金县| 兴和县| 遂川县| 多伦县| 古田县| 高安市| 湖州市| 筠连县| 黄石市| 景德镇市| 克什克腾旗| 东阳市| 永宁县| 榕江县| 平定县| 吐鲁番市| 龙海市| 涿州市| 朝阳区| 蚌埠市| 鹤壁市| 长宁区| 博湖县| 太和县| 石门县| 永仁县|