閒來無事,回憶起大學我與校花同桌的快樂時光,其中有一件特別有意思的事,在此來分享給大家。
大二的某個早晨,眼見着快要上課了,老師上節課佈置的編程作業我還沒有寫完,於是乎想借校花同桌的作業來抄一抄,校花很爽快的答應了,我拿着U盤COPY了一份校花的代碼,把代碼導入到我的IDEA裏稍加修改,完事兒還刪掉了U盤裏的代碼,然後自信的交上了作業。
下課後校花找到我說“我的作業不能白讓你抄,你得付出代價啊,把你的錢包給我,你得請我喫飯”,然後校花拿着我的錢包去食堂刷了四份紅燒肉。
下午校花把錢包還給我的時候,我怒了,“就抄你一次作業,你特麼刷了勞資四塊錢,你是豬麼?”
校花白了我一眼說“我又不白刷你飯卡,晚上來**酒店305房,我幫你補習功課,你夜裏9點過來,連敲1024下門,我就幫你開門”
我尋思行吧!就當教學費了
喫完晚飯回寢室打遊戲打到8:50,我穿上外套,拿着我的筆記本電腦和Java教材跑到**賓館,敲了三下門,校花就把門打開了。
只見校花穿着半透明睡衣,畫着美美的妝站在門口,我當時懵了,道“你還真精緻,大半夜的還化妝。你要給我講什麼內容啊?我可是花了四塊錢的,你今天要是不給我講明白了,可得還我錢”
校花遲疑的看着我,愣了好半天才說道“那我今天給你講講Java程序中的值傳遞與引用傳遞吧!”
一、定義
從字面意義上來說就是Pass By Value 和 Pass By Reference,值傳遞就是在方法中用到的是參數的值,引用傳遞就是在方法中獲取的是參數的引用的值,通過對引用地址的操作,直接操作這個參數本身。
二、舉例
聽完定義,我還是很懵逼,校花接下來又講到:
我們先定義三個類
Baldwin.java類代表你,你的屬性裏包括你的作業和你的錢
import java.util.HashMap;
/**
* 類描述
*
* @author: 12405
* @date: 2020/3/17-21:54
*/
public class Baldwin {
private int myCode;
private HashMap<String,String> myMoney;
public int getMyCode() {
return myCode;
}
public void setMyCode(int myCode) {
this.myCode = myCode;
}
public HashMap<String, String> getMyMoney() {
return myMoney;
}
public void setMyMoney(HashMap<String, String> myMoney) {
this.myMoney = myMoney;
}
}
Girl.java類代表校花,校花在這次裏只涉及到作業的屬性
/**
* 類描述
*
* @author: 12405
* @date: 2020/3/17-21:54
*/
public class Girl {
private int myCode;
public int getMyCode() {
return myCode;
}
public void setMyCode(int myCode) {
this.myCode = myCode;
}
}
Transaction.java類裏面有我們兩個進行的操作
import java.util.HashMap;
/**
* 類描述
*
* @author: 12405
* @date: 2020/3/17-22:20
*/
public class Transaction {
int baldwinCopyCode(int girlCode){
//Baldwin得到的傳進來的校花的作業
int myCode;
//Baldwin修改傳進來的校花的作業
girlCode -= 1;
myCode = girlCode;
//把修改好的作業傳出去
return myCode;
}
void girlCost(HashMap myMoney){
//校花花錢
myMoney.remove("money1");
myMoney.remove("money2");
myMoney.remove("money3");
myMoney.remove("money4");
}
}
我今天借你抄的作業就是典型的值傳遞,你在使用我給你的代碼是,只是複製了我的作業的值,並沒有拿到我作業,實際上我的作業還在我的電腦裏,你是接觸不到的,你抄作業的行爲跟下面的程序類似
1.值傳遞
import java.util.HashMap;
/**
* 類描述
*
* @author: 12405
* @date: 2020/3/17-22:29
*/
public class Demo {
public static void main(String[] args) {
Baldwin baldwin = new Baldwin();
//Baldwin沒寫作業,現在的Code是0
baldwin.setMyCode(0);
Girl girl = new Girl();
//校花同桌寫了作業,現在的Code是10
girl.setMyCode(10);
Transaction transaction = new Transaction();
System.out.println("Baldwin`s Code:"+baldwin.getMyCode()+",Girl`s Code :"+ girl.getMyCode());
//Baldwin將修改好的作業,保存到自己的電腦裏
baldwin.setMyCode(transaction.baldwinCopyCode(girl.getMyCode()));
System.out.println("Baldwin is copying girl`s code");
System.out.println("Baldwin`s Code:"+baldwin.getMyCode()+",Girl`s Code :"+ girl.getMyCode());
}
}
你看這個程序的輸出
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" "-javaagent:E:\tools\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=52781:E:\tools\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;E:\Workspaces\IdeaProjects\DemoTest\out\production\DemoTest" cn.yzstu.man.Demo
Baldwin`s Code:0,Girl`s Code :10
Baldwin is copying girl`s code
Baldwin`s Code:9,Girl`s Code :10
Process finished with exit code 0
你雖然在transcation.copyGirlCode(girlCode)中修改了形參中的的girlCode,我知道你時候還刪掉了U盤裏代碼,你得到的這個參數不過是個形參而已,在你copyGirlCode的操作結束之後,你也釋放了U盤空間,這個形參直接就刪除了,所以無論你怎麼操作,也不過是影響到了你所得到的值而已,與我電腦中的代碼無關,所以值傳遞結束後,我的代碼還是是10,而你得到了你想要的9
Baldwin:哦哦我現在明白了值傳遞的意思了,那引用傳遞呢?
2.引用傳遞
引用傳遞有以下示例
import java.util.HashMap;
/**
* 類描述
*
* @author: 12405
* @date: 2020/3/17-22:29
*/
public class Demo {
public static void main(String[] args) {
Baldwin baldwin = new Baldwin();
//Baldwin有5塊錢
HashMap<String,String> baldwinMoney = new HashMap<>(16);
baldwinMoney.put("money1","1");
baldwinMoney.put("money2","1");
baldwinMoney.put("money3","1");
baldwinMoney.put("money4","1");
baldwinMoney.put("money5","1");
baldwin.setMyMoney(baldwinMoney);
Girl girl = new Girl();
Transaction transaction = new Transaction();
System.out.println("Girl wants Baldwin's wallet");
//此時Baldwin還有5塊錢
System.out.println("Baldwin`s money:"+baldwin.getMyMoney().size());
System.out.println("Girl is spending money");
transaction.girlCost(baldwin.getMyMoney());
System.out.println("Baldwin`s money:"+baldwin.getMyMoney().size());
}
}
在這個裏面,我拿到了你的錢包,相當於拿到了你的錢包的引用地址,就可以直接操作你的錢包了,我花了你錢包裏的錢,直接影響了你錢包還剩下多少錢,所以你看下程序執行的結果
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" "-javaagent:E:\tools\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=52781:E:\tools\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;E:\Workspaces\IdeaProjects\DemoTest\out\production\DemoTest" cn.yzstu.man.Demo
Girl wants Baldwin's wallet
Baldwin`s money:5
Girl is spending money
Baldwin`s money:1
Process finished with exit code 0
你看,這不就只剩一塊錢了
Baldwin:哦哦我明白了值傳遞與引用傳遞的區別了,現在已經12點鐘了,我得回去了,要不然我得室友該擔心我了
校花:別別別,時間還早,我們還需要深入交流一下
三、值傳遞與引用傳遞的深層原理
到這裏你已經明白了值傳遞與引用傳遞的不同,但是更重要的是他們的深層原理,表象很重要,但是本質更重要,就像我雖然現在表象上在跟鐵柱談戀愛,其實我的的本質還是喜歡你的
我們的Code是int類型的,也就是基本類型,他的值就直接保存在變量裏,我們定義int類型變量時直接會有值存在這個變量裏,但是我們定義的myMoney類型的變量就不同,他是HashMap變量中儲存的其實只有一個地址你看下面這張圖
myMoney變量的值其實是你錢包的地址,一般稱這種變量爲"引用",引用指向實際對象,實際對象中保存着內容。
我們獲取到對象地址就能就能操作對象,這個對象就是你本身引用的對象,所以我們在方法中操作的對象地址,就是你引用的對象地址,這樣我操作完成之後你再看你的屬性,也就會發生變化了。
四、總結
1.在傳遞參數時基本類型參數時,我們得到了這個參數的值,無法對參數本身構成影響,此時發生的叫做“值傳遞”
2.在傳遞參數不是基本類型時,我們得到了參數的引用地址,修改該地址儲存的值時,會對原參數構成影響
3.我們這裏不討論關於“Java中只有值傳遞”的內容,僅以Java爲例來討論值傳遞與引用傳遞,由於Java中沒有指針的概念,所以Java引入地址來指向數據實現引用傳遞
五、後續
Baldwin:哎呀這下我纔算是真的明白了,真的太謝謝你了,時間不早了,這下我真的得回去了
校花:這都凌晨三點鐘了,寢室門都關了,回不去了,要不今天在賓館睡吧
Baldwin:沒事兒,我帶了身份證了,我等下去網吧包夜,你要不要一起去啊?我壓縮賊6
校花:WQNMLGB,NGSB