128
阿裏雲
技術社區[雲棲]
理解JAVA的傳值方式
問題: Java的參數傳遞的是值還是引用?
我們經常會被問到這樣的問題,當我調用某個方法時,通過參數傳遞過去的是變量本身,還是一個變量的複製品?問題的答案留到討論後給出。
首先,你需要了解下java變量的分類:java中的變量分為
- 基本類型
- 接口類型
- 類類型
- 數組類型
其中後麵三種統稱為引用類型,而基本類型分為三種,
- 數字類型
- boolean
- returnAddress
數字類型又分為
- 浮點類型
- 整數類型
- 浮點
整數又有具體的內容,這裏不再展開說明。其中,returnAddress是java虛擬機內部使用的類型,它被用來實現java程序中finally子句。這裏主要看引用類型和基本類型數字類型情況(boolean類型的情況和基本類型一致).
先看參數為基本類型的情況:
02 |
public void swap( int a, int b) {
|
06 |
System.out.println( "swap: a=" + a + ",b=" + b);
|
09 |
public static void main(String[] args) {
|
10 |
Demo1 demo1 = new Demo1();
|
14 |
System.out.println( "main: a=" + a + ",b=" + b);
|
輸出
上麵的代碼想通過swap交互a和b的值,在swap內部,變量a和b已經交換成功了,但在main中a和b的值依然是原來的值.
再看參數為引用的情況:
02 |
<pre> public class Demo2 {
|
03 |
public void swap(StringBuffer a,StringBuffer b){
|
07 |
System.out.println( "swap: a=" +a+ ",b=" +b);
|
10 |
public static void main(String[] args) {
|
11 |
StringBuffer a = new StringBuffer( "a" );
|
12 |
StringBuffer b = new StringBuffer( "b" );
|
13 |
Demo2 demo2 = new Demo2();
|
15 |
System.out.println( "main: a=" +a+ ",b=" +b);
|
大家可以先思考下,上麵的輸出是什麼?
輸出:
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指向的對象的值.再看下麵的例子:
03 |
public void swap(StringBuffer a,StringBuffer b){
|
08 |
System.out.println( "swap: a=" +a+ ",b=" +b);
|
10 |
public static void main(String[] args) {
|
11 |
StringBuffer a = new StringBuffer( "a" );
|
12 |
StringBuffer b = new StringBuffer( "b" );
|
13 |
Demo3 demo3 = new Demo3();
|
15 |
System.out.println( "swap: a=" +a+ ",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傳遞的隻會是值,沒有傳遞引用.
最後更新:2017-05-22 14:32:48