我與校花同桌之間的金錢交易(又名:戲說值傳遞與引用傳遞,這還看不懂你來打我)

閒來無事,回憶起大學我與校花同桌的快樂時光,其中有一件特別有意思的事,在此來分享給大家。

大二的某個早晨,眼見着快要上課了,老師上節課佈置的編程作業我還沒有寫完,於是乎想借校花同桌的作業來抄一抄,校花很爽快的答應了,我拿着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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章