前言
我們都知道坡脐,java中數(shù)據(jù)類型分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型卢佣。
-
基本數(shù)據(jù)類型
- 整型:byte,short栋豫,int挤安,long
- 浮點型:float,double
- 字符型:char
- 布爾型:boolean
-
引用數(shù)據(jù)類型
- 數(shù)組
- 類
- 接口
方法的參數(shù)分為實際參數(shù)丧鸯,和形式參數(shù)蛤铜。
- 形式參數(shù):定義方法時寫的參數(shù)
- 實際參數(shù):調(diào)用方法時寫的具體數(shù)值
一般情況下,在數(shù)據(jù)做為參數(shù)傳遞的時候丛肢,基本數(shù)據(jù)類型是值傳遞围肥,引用數(shù)據(jù)類型是引用傳遞(地址傳遞)
值傳遞
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
swap(num1, num2);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
}
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
運行的結(jié)果是:
a = 20
b = 10
num1 = 10
num2 = 20
流程:
- 主函數(shù)進棧,num1摔踱、num2初始化虐先。
- 調(diào)用swap方法怨愤,swap( )進棧派敷,將num1和num2的值,復(fù)制一份給a和b。
- swap方法中對a篮愉、b的值進行交換腐芍。
- swap方法運行完畢,a试躏、b的值已經(jīng)交換猪勇。
- swap方法彈棧。
- 主函數(shù)彈棧颠蕴。
解析:
在swap方法中泣刹,a、b的值進行交換犀被,并不會影響到num1椅您、num2。因為寡键,a掀泳、b中的值,只是從num1西轩、num2的復(fù)制過來的员舵。 也就是說,a藕畔、b相當(dāng)于num1马僻、num2的副本,副本的內(nèi)容無論怎么修改注服,都不會影響到原件本身巫玻。
引用傳遞
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println(arr[0]);
}
//將數(shù)組的第一個元素變?yōu)?
public static void change(int[] array) {
int len = array.length;
array[0] = 0;
}
運行的結(jié)果是:
0
流程:
- 主函數(shù)進棧,int[] arr初始化祠汇。
- 調(diào)用change方法仍秤,change( )進棧,將arr的地址值可很,復(fù)制一份給array诗力。
- change方法中,根據(jù)地址值我抠,找到堆中的數(shù)組苇本,并將第一個元素的值改為0。
- change方法運行完畢菜拓,數(shù)組中第一個元素的值已經(jīng)改變瓣窄。
- change方法彈棧。
- 主函數(shù)彈棧纳鼎。
解析:
調(diào)用change()的時候俺夕,形參array接收的是arr地址值的副本裳凸。并在change方法中,通過地址值劝贸,對數(shù)組進行操作姨谷。change方法彈棧以后,數(shù)組中的值已經(jīng)改變映九。main方法中梦湘,打印出來的arr[0]也就從原來的1變成了0.
無論是主函數(shù),還是change方法件甥,操作的都是同一個地址值對應(yīng)的數(shù)組捌议。
就像你把自己家的鑰匙給了另一個人,這個人拿著鑰匙在你家一頓瞎折騰引有,然后走了禁灼。等你拿著鑰匙回到家以后,家里已經(jīng)變成了被折騰過后轿曙,慘不忍睹的樣子弄捕。。
這里的鑰匙就相當(dāng)于地址值导帝,家就相當(dāng)于數(shù)組本身守谓。
String類型傳遞
public static void main(String[] args) {
String str = "AAA";
change(str);
System.out.println(str);
}
public static void change(String s) {
s = "abc";
}
運行的結(jié)果是:
AAA
String是一個類,類是引用數(shù)據(jù)類型您单,做為參數(shù)傳遞的時候斋荞,應(yīng)該是引用傳遞。但是從結(jié)果看起來卻是值傳遞
原因:
String的API中有這么一句話:“their values cannot be changed after they are created”虐秦,
意思是:String的值在創(chuàng)建之后不能被更改平酿。
API中還有一段:
String str = "abc";
等效于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
也就是說:對String對象str的任何修改 等同于 重新創(chuàng)建一個對象,并將新的地址值賦值給str悦陋。
這樣的話蜈彼,上面的代碼就可以寫成:
public static void main(String[] args) {
String str1 = "AAA";
change(str1);
System.out.println(str1);
}
public static void change(String s) {
char data[] = {'a', 'b', 'c'}
String str = new String(data);
s = str;
}
流程:
- 主函數(shù)進棧,str1初始化俺驶。
- 調(diào)用change方法幸逆,change( )進棧,將str1的地址值暮现,復(fù)制一份給s还绘。
- change方法中,重現(xiàn)創(chuàng)建了一個String對象”abc”栖袋,并將s指向了新的地址值拍顷。
- change方法運行完畢,s所指向的地址值已經(jīng)改變塘幅。
- change方法彈棧昔案。
- 主函數(shù)彈棧尿贫。
解析:
String對象做為參數(shù)傳遞時,走的依然是引用傳遞爱沟,只不過String這個類比較特殊帅霜。
String對象一旦創(chuàng)建匆背,內(nèi)容不可更改呼伸。每一次內(nèi)容的更改都是重現(xiàn)創(chuàng)建出來的新對象。
當(dāng)change方法執(zhí)行完畢時钝尸,s所指向的地址值已經(jīng)改變括享。而s本來的地址值就是copy過來的副本,所以并不能改變str1的值珍促。
String類型類似情況:
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person("張三");
change(p);
System.out.println(p.name);
}
public static void change(Person p) {
Person person = new Person("李四");
p = person;
}
}
運行的結(jié)果是:
張三
總結(jié)
- 值傳遞的時候铃辖,將實參的值,copy一份給形參猪叙。
- 引用傳遞的時候娇斩,將實參的地址值,copy一份給形參穴翩。
也就是說犬第,不管是值傳遞還是引用傳遞,形參拿到的僅僅是實參的副本芒帕,而不是實參本身歉嗓。