方法調用是編程語言中非常重要的一個特性,在方法調用時,通常需要傳遞一些參數來完成特定功能。
我們首先觀察一個簡單的例子:
public class Test extends A {
public static void main(String []args){
String str1 = "A";
StringBuffer str2 = new StringBuffer("B");
setValues(str1,str2);
System.out.println("str1="+str1);
System.out.println("str2="+str2);
}
static void setValues(String str1,StringBuffer str2){
str1 = "hello";
str2 = str2.append("hello word");
}
}
運行的結果如下:
str1=A
str2=Bhello word
是不是和我們之前的預想有一定的差距?接下來我們慢慢來弄懂為什么會是這個樣子的。首先我們需要了解兩個概念:
值傳遞
<strong>在方法調用中,實參會把它的值傳遞給形參,形參只是用實參的值初始化一個零食的存儲單元,因此形參與實參雖然有著相同的值,但是卻有著不同的存儲單元,因此對形參的改變不會影響實參的值。</strong>
引用傳遞
<strong>在方法調用中,傳遞的是對象(也可以看做是對象的地址),這時形參與實參的對象指向同一塊存儲單元,因此對形參的修改會影響實參的值。</strong>r
明白了上面的兩個概念之后,我們用一幅圖來表示上面程序參數的改變過程。(在java中String對象是值傳遞,StringBuffer是應用傳遞,后面會有介紹。)
為了方便理解,假設str1和str2的存儲單元分別為0xfffffff1和0xfffffff2。在調用方法setValues()時,String傳遞的是一個值,此時修改的是傳遞過來的副本的值,并不會影響到str1的值。而str2傳遞的是引用,在setValues方法修改該值的方法,會直接影響到其值。具體可以參加示意圖。
java中處理8中基本的數據類型用的是值傳遞,其他的所有類型都是引用傳遞。下面列出這8中基礎的數據類型。
數據類型 | 字節長度 | 范圍 | 默認值 | 包裝類 |
---|---|---|---|---|
int | 4 | [-231~231-1] | 0 | Integer |
short | 2 | [-32768~32767] | 0 | Short |
long | 8 | [-263~263-1] | 0L或者ol | Long |
byte | 1 | [-128~127] | 0 | Byte |
float | 4 | 32位IEEE754單精度范圍 | 0.0F或者0.0f | Float |
double | 8 | 32位IEEE754雙精度范圍 | 0.0 | Double |
char | 2 | [0,65536] | u0000 | Characher |
boolean | 1 | true/false | false | Bollean |
但是需要注意的是,8中基本數據類型的包裝類都是不可變量,但是都是按引用傳遞。
Integer a=1;
Integer b=a;
b++;
System.out.println(b);
在上面的實例中,會輸出2.但是別誤會。由于Integer是不可變類,因此沒有提供改變他值的方法,這里的b在執行完b++語句后,此時會創建一個新的值為2的Integer賦值給b,此時b和a其實已經沒有任何關系了。所以Integer其實質還是按引用傳遞,不要被上面的表象模糊了。