工作中,發現大多數人對值傳遞,引用傳遞理解不深,下面寫一遍文章詳細聊聊。
一、形參
形參:用來接收調用方法時傳遞的參數,只有在被調用時才分配內存,一旦調用結束,就釋放內存空間。因此僅在方法內有效。
public void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
這里a,b就是形參,方法結束時,在棧空間就會被銷毀。
二、實參
調用上面方法swap(6, 8); 其中6 8就是實參。
三、值傳遞和引用傳遞
- 值傳遞:方法調用時,實際參數將它的值傳遞給形式參數,函數就收到的是原始值的副本,此時內存中存在兩個相同的基本類型,若方法中對形參執行處理操作,並不會影響實際參數的值。
- 引用傳遞:方法調用時,實際參數的引用(指內存地址,不是參數的值)被傳遞給方法中相應的形式參數,函數接受到的是原始值的內存地址,在方法中,形參和實參的內容(地址)相同,方法中對形參的處理會影響實參的值。
public class People {
private String name;
private String age;
public People(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
public class Base1 {
public static void main(String[] args) {
int a = 10;
// 按值傳遞
test1(a);
System.out.println("main a==" + a);
People p = new People("rose", "18");
// 按引用傳遞
test2(p);
System.out.println("main name==" + p.getName() +", age==" + p.getAge());
}
public static void test1(int a) {
a = 20;
System.out.println("test1 a==" + a);
}
public static void test2(People p) {
p.setName("jack");
p.setAge("19");
System.out.println("test2 name==" + p.getName() +", age==" + p.getAge());
}
}
輸出結果:
test1 a==20
main a==10
test2 name==jack, age==19
main name==jack, age==19
結論:
- 形參為基本類型時,對形參的處理不會影響實參。
- 形參為應用類型時,對形參的處理會影響實參。
- String、Integer、Double等immutable類型,因為本身沒有提供修改函數的操作,每次操作都是生成一個新對象,所以要特殊對待,可以理解為值傳遞,形參操作不會影響實參對象。
四、java對象及引用
以上面的People為例,構建一個對象:People p1 = new People("jack", "19");
其實這個對象包含四個動作。
- 右邊的new People,是以People類為模板,在堆空間創建一個People類對象。
- 末尾的("jack", "19"),指的是對象創建后,調用的構造函數,對剛生成的對象進行初始化。
- 左邊的People p1創建了一個People類引用變量,所謂People類引用,就是以后可以用來指向People對象的引用。
- = 操作符使對象引用指向剛創建的People對象。
People p1;
p1 = new People("jack", "19");
上面兩條語句等價於 People p1 = new People("jack", "19");
這樣看就很明白,一個是對象應用變量,一個是對象實體。
如果只執行第一條,還沒執行第二條此時創建的p1還沒指向任何一個對象,它的值是null。
再來一句:
People p2;
p2 = p1;
這里發生了復制行為,對象本身沒有復制,被復制的只是對象的引用。結果是p2也指向了p1的對象。
再來一句:
p2 = new People("rose", "18");
此時p2指向了第二個對象,此時得出結論:
一個對象引用可以指向0個或者1個對象。
一個對象可以有N個引用指向它。
再來一句:
p1 = p2;
此時p1指向p2這個對象,至於之前的p1這個對象,它已成為垃圾回收機制的處理對象。
四、java中方法參數的引用傳遞
“當一個對象被當作參數傳遞到一個方法”,這就是所謂的引用傳遞。
public class Base2 {
public static void main(String[] args) {
People p = new People("jordon","23");
// changePeople1(p);
changePeople2(p);
System.out.println(p.getName() + "===" + p.getAge());
}
public static void changePeople1(People p) {
p.setName("kobe");
p.setAge("24");
}
public static void changePeople2(People p) {
p.setName("kobe");
p.setAge("24");
p = new People("james", "24");
}
}
以上代碼調用changePeople1和changePeople2都是輸出
kobe===24
我們來分析下為什么了??