理解JAVA的傳值方式
作者:黑伯
問題: Java的引數傳遞的是值還是引用?
我們經常會被問到這樣的問題,當我呼叫某個方法時,通過引數傳遞過去的是變數本身,還是一個變數的複製品?問題的答案留到討論後給出。
首先,你需要了解下java變數的分類:java中的變數分為
- 基本型別
- 介面型別
- 類型別
- 陣列型別
其中後面三種統稱為引用型別,而基本型別分為三種,
- 數字型別
- boolean
- returnAddress
數字型別又分為
- 浮點型別
- 整數型別
- 浮點
整數又有具體的內容,這裡不再展開說明。其中,returnAddress是java虛擬機器內部使用的型別,它被用來實現java程式中finally子句。這裡主要看引用型別和基本型別數字型別情況(boolean型別的情況和基本型別一致).
先看引數為基本型別的情況:
public class Demo1 { public void swap(int a, int b) { a = a ^ b; b = a ^ b; a = a ^ b; System.out.println("swap: a=" + a + ",b=" + b); } public static void main(String[] args) { Demo1 demo1 = new Demo1(); int a = 1; int b = 2; demo1.swap(a, b); System.out.println("main: a=" + a + ",b=" + b); } }
輸出
swap: a=2,b=1 main: a=1,b=2
上面的程式碼想通過swap互動a和b的值,在swap內部,變數a和b已經交換成功了,但在main中a和b的值依然是原來的值.
再看引數為引用的情況:
</pre> <pre>public class Demo2 { public void swap(StringBuffer a,StringBuffer b){ StringBuffer c = a; a=b; b=c; System.out.println("swap: a="+a+",b="+b); } public static void main(String[] args) { StringBuffer a = new StringBuffer("a"); StringBuffer b = new StringBuffer("b"); Demo2 demo2 = new Demo2(); demo2.swap(a, b); System.out.println("main: a="+a+",b="+b); } }</pre> <pre>
大家可以先思考下,上面的輸出是什麼?
輸出:
swap: a=b,b=a
main: a=a,b=b
和引數為基本型別的情況結果是一致的.
為什麼會出現這種情況呢?
我們來分析下上面的引數傳遞過程,以Demo2為例:
圖1是swap未計算前的引數值,
圖2是swap計算後的引數值.
從圖中可以看出,swap的計算過程只能改變swap內部變數a和b的值,不能改變main中的a和b變數的引用值,換言之,引數的傳遞只能傳值,不存在傳引用一說.
請注意,上面我說不能改變a和b變數的引用值,可沒說不能改變a和b指向的物件的值.再看下面的例子:
</pre> public class Demo3 { public void swap(StringBuffer a,StringBuffer b){ a.append(b); StringBuffer c = a; a=b; b=c; System.out.println("swap: a="+a+",b="+b); } public static void main(String[] args) { StringBuffer a = new StringBuffer("a"); StringBuffer b = new StringBuffer("b"); Demo3 demo3 = new Demo3(); demo3.swap(a, b); System.out.println("swap: a="+a+",b="+b); } } 這個會輸出什麼呢? swap: a=b,b=ab swap: a=ab,b=b
這個就是上面所說的,在swap內部的計算過程中,改變了main.a所指向物件的值.
就像下面的圖所描述的那樣:
、
但根本上,swap不能改變main中a和b的引用值.
另外貼一句sun公司官方文件上的描述這一問題的原話:
Java is always pass-by-value.when object is passed as a argument, be careful with that it is also the copy of reference
所以,現在你應該知道,java傳遞的只會是值,沒有傳遞引用.