java的值傳遞和引用傳遞
一:搞清楚 基本類型 和 引用類型的不同之處
int num = 10; String str = "hello";
如圖所示,num是基本類型,值就直接保存在變量中。而str是引用類型,變量中保存的只是實際對象的地址。一般稱這種變量為"引用",引用指向實際對象,實際對象中保存着內容。
二:搞清楚賦值運算符(=)的作用
num = 20; str = "java";
對於基本類型 num ,賦值運算符會直接改變變量的值,原來的值被覆蓋掉。
對於引用類型 str,賦值運算符會改變引用中所保存的地址,原來的地址被覆蓋掉。但是原來的對象不會被改變(重要)。
如上圖所示,"hello" 字符串對象沒有被改變。(沒有被任何引用所指向的對象是垃圾,會被垃圾回收器回收)
一個段有趣和令人困惑的代碼
1 public static void main(String[] args){ 2 String str = new String("ab"); 3 change(str); 4 System.out.println(str); 5 } 6 7 public static void change(String str){ 8 str = "cd"; 9 }
結果為:ab
常見的困惑問題
x存儲指向堆中的“ab”字符串的引用。所以,當x被作為參數傳遞到change()方法時,它仍然指向堆中“ab”,像下面這樣:
因為java是按值傳遞的(pass-by-value), x的值是“ab”的引用。當方法的change()被調用,它會創建一個新的“cd”的對象,而x現在是指向“cd”像下面這樣:
這似乎是一個相當合理的解釋。他們明確表示,Java是總是傳遞按值。但是,錯在哪里呢?
代碼真正做了些什么呢?
上面的解釋有幾個錯誤。為了容易理解這一點,這是一個好主意,簡單地描述整個過程。
當字符串“ab”被創建,java分配存儲字符串對象所需的內存空間。然后,將對象分配給變量x,該變量是被實際分配的引用對象。此引用是該對象被存儲在內存的地址。
變量x包含一個字符串對象的引用。 x不是引用本身!它是用於存儲一個引用(內存地址)的變量。
Java是僅僅是按值傳遞。當x傳遞給change()方法,x的(引用)值的副本被傳遞。方法change()創建另一個對象“cd”,它有一個不同的引用。它是被改變的x副本指向“cd”的變量,而不是x引用本身。
下面的圖表展現了真實的過程:
總結:實際上JAVA在方法里傳遞的只是對象的副本。